Merge branch 'master' into task/host-meta-2-rationale

This commit is contained in:
Daniel Gultsch 2024-03-10 09:23:30 +01:00 committed by GitHub
commit 910b2079d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 1267 additions and 134 deletions

View File

@ -16,7 +16,7 @@ jobs:
- name: Detect changes to XEP files
id: changed-xeps
uses: tj-actions/changed-files@v34
uses: tj-actions/changed-files@v41
with:
files: |
xep-*.xml
@ -31,5 +31,11 @@ jobs:
if ! tools/validate-xep0001-conformance.sh "$xep"; then
result=1
fi
if [[ ${xep} == xep-* ]]; then
echo Checking ${xep} by invoking \"make .${xep}.check.ok\"
if ! make ".${xep}.check.ok"; then
result=1
fi
fi
done
exit $result

2
.gitignore vendored
View File

@ -75,3 +75,5 @@ Session.vim
/tools/xeps-email.conf
/tmp/
/pr-worktree/
.*.xml.check.ok

View File

@ -1,5 +1,3 @@
.SILENT:
OUTDIR?=build
REFSDIR?=$(OUTDIR)/refs
EXAMPLESDIR?=$(OUTDIR)/examples
@ -36,6 +34,7 @@ xep_pdfs=$(patsubst %.xml,$(OUTDIR)/%.pdf,$(xeps))
xep_refs=$(patsubst xep-%.xml, $(REFSDIR)/reference.XSF.XEP-%.xml, $(xeps))
xep_examples=$(patsubst xep-%.xml, $(EXAMPLESDIR)/%.xml, $(xeps))
all_xep_check_ok=$(patsubst %.xml, .%.xml.check.ok, $(xeps))
.PHONY: help
help:
@ -46,6 +45,7 @@ help:
@echo ' refs - build all IETF refs'
@echo ' html - build all XEPs'
@echo ' inbox-html - build all ProtoXEPs'
@echo ' check - check all XEPs for errors'
@echo ' clean - recursively unlink the build tree'
@echo ' preview - builds html whenever an XEP changes (requires inotify-tools)'
@echo ' examples - extract all examples'
@ -82,6 +82,9 @@ refs: $(xep_refs)
.PHONY: examples
examples: $(xep_examples)
.PHONY: check
check: $(all_xep_check_ok)
.PHONY: xep-%
xep-%: $(OUTDIR)/xep-%.html $(REFSDIR)/reference.XSF.XEP-%.xml $(OUTDIR)/xep-%.pdf $(EXAMPLESDIR)/%.xml;
@ -106,30 +109,24 @@ $(EXAMPLESDIR)/%.xml: xep-%.xml $(XMLDEPS) examples.xsl | $(EXAMPLESDIR)
$(REFSDIR)/reference.XSF.XEP-%.xml: xep-%.xml $(XMLDEPS) ref.xsl | $(REFSDIR)
xsltproc --path $(CURDIR) ref.xsl "$<" > "$@" && echo "Finished building $@"
$(xep_htmls): $(OUTDIR)/xep-%.html: xep-%.xml $(XMLDEPS) $(HTMLDEPS) | $(OUTDIR)
.%.xml.check.ok: %.xml
xmllint --nonet --noout --noent --loaddtd --valid "$<"
# Check for non-data URIs
! xmllint --nonet --noout --noent --loaddtd --xpath "//img/@src[not(starts-with(., 'data:'))]" $< 2>/dev/null && true
# Check for non-data URIs, the result set of the XPath expression below should be empty
# Disabled for now, see
# https://github.com/xsf/xeps/issues/1316 and https://gitlab.gnome.org/GNOME/libxml2/-/issues/673
# xmllint --loaddtd --xpath "//img/@src[not(starts-with(., 'data:'))]" $< > /dev/null
touch $@
# Actually build the HTML
$(xep_htmls): $(OUTDIR)/xep-%.html: xep-%.xml $(XMLDEPS) $(HTMLDEPS) | $(OUTDIR)
xsltproc --path $(CURDIR) --param htmlbase "$(if $(findstring inbox,$<),'../','./')" xep.xsl "$<" > "$@" && echo "Finished building $@"
$(proto_xep_htmls): $(OUTDIR)/inbox/%.html: inbox/%.xml $(XMLDEPS) $(proto_HTMLDEPS) | $(OUTDIR)
xmllint --nonet --noout --noent --loaddtd --valid "$<"
# Check for non-data URIs
! xmllint --nonet --noout --noent --loaddtd --xpath "//img/@src[not(starts-with(., 'data:'))]" $< 2>/dev/null && true
# Actually build the HTML
xsltproc --path $(CURDIR) --param htmlbase "$(if $(findstring inbox,$<),'../','./')" xep.xsl "$<" > "$@" && echo "Finished building $@"
$(OUTDIR)/xmpp.pdf $(OUTDIR)/xmpp-text.pdf: | $(OUTDIR)
cp "resources/$(notdir $@)" "$@"
$(OUTDIR)/%.pdf: %.xml $(XMLDEPS) $(TEXMLDEPS)
xmllint --nonet --noout --noent --loaddtd --valid "$<"
# Check for non-data URIs
! xmllint --nonet --noout --noent --loaddtd --xpath "//img/@src[not(starts-with(., 'data:'))]" $< 2>/dev/null && true
xsltproc --path $(CURDIR) xep2texml.xsl "$<" > "$(@:.pdf=.tex.xml)"
texml -e utf8 "$(@:.pdf=.tex.xml)" "$(@:.pdf=.tex)"
sed -i -e 's|\([\s"]\)\([^"]http://[^ "]*\)|\1\\path{\2}|g' \

View File

@ -0,0 +1,268 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM '../xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep xmlns="">
<header>
<title>PubSub Server Information</title>
<abstract>This document defines a data format whereby basic information of an XMPP domain can be expressed and exposed over pub-sub.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies/>
<supersedes/>
<supersededby/>
<shortname>serverinfo</shortname>
<author>
<firstname>Guus</firstname>
<surname>der Kinderen</surname>
<email>guus.der.kinderen@gmail.com</email>
<jid>guus.der.kinderen@igniterealtime.org</jid>
</author>
<revision>
<version>0.0.1</version>
<date>2023-12-19</date>
<initials>gdk</initials>
<remark>
<ul>
<li>Initial version.</li>
</ul>
</remark>
</revision>
</header>
<section1 topic="Introduction" anchor="intro">
<p>To facilitate discovery of information of individual domains in an XMPP-based network, this specification defines a data format to define basic information for individual XMPP domains. By leveraging &xep0060; this information can efficiently be shared with applications that compose an overview of the larger XMPP network.</p>
</section1>
<section1 topic="Requirements" anchor="requirements">
<ul>
<li>Describe links between nodes in an XMPP-based network, by enumerating connections used for federation between XMPP domains.</li>
<li>An extensible data format, allowing additional data (such as that defined in &xep0092;) to be retrievable without requiring additional round-trips.</li>
</ul>
</section1>
<section1 topic="Discovering Support" anchor="disco">
<p>Domains supporting the publication of Server Information data, as described in this document, MUST advertise the fact by announcing a &xep0030; feature of 'urn:xmpp:serverinfo:0'. This signifies that an administrative entity approved the publication of data, which is important for the opt-in mechanism described in <link url="#privacy">Privacy Considerations section</link> of this document.</p>
<p>The pub-sub service address and node in which Server Information data is advertised SHOULD be specified using a &xep0128;, using an URI as specified in section 12.22 of XEP-0060. These pub-sub coordinates MUST be scoped using a FORM_TYPE of "http://jabber.org/network/serverinfo" (as specified in XEP-0157) and data form field registered for this purpose as defined in the <link url="#registrar">XMPP Registrar Considerations section</link> of this document.</p>
<p>When the 'urn:xmpp:serverinfo:0' feature but no corresponding Service Discovery Extension is advertised, the node that is used will be a first-level leaf node using the name 'serverinfo' on the first pub-sub service advertised through service discovery.</p>
<example caption="Service Discovery information request"><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='shakespeare.lit'
id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]></example>
<example caption="Service Discovery information response"><![CDATA[
<iq type='result'
from='shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='urn:xmpp:serverinfo:0'/>
...
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/network/serverinfo</value>
</field>
<field var='serverinfo-pubsub-node'>
<value>xmpp:pubsub.shakespeare.lit?;node=serverinfo</value>
</field>
</x>
</query>
</iq>]]></example>
<p>The node MUST reference a first-level leaf node on a pub-sub service.</p>
<example caption="Entity queries root node for information"><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='info1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='serverinfo'/>
</iq>]]></example>
<example caption="Service responds with identity of pubsub/leaf"><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='info1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='serverinfo'>
...
<identity category='pubsub' type='leaf'/>
...
</query>
</iq>]]></example>
</section1>
<section1 topic="Data Format" anchor="impl">
<p>The data format uses an element named 'serverinfo' in the namespace 'urn:xmpp:serverinfo:0'. In its minimal form, it defines each XMPP domain name served by the local server in an attribute named 'name'.</p>
<example caption="Minimal Data Format"><![CDATA[
<serverinfo xmlns='urn:xmpp:serverinfo:0'>
<domain name='shakespeare.lit'/>
</serverinfo>]]></example>
<p>The optional 'federation' child element is used to denote remote XMPP domains with which the local domain is federating. Each of them are represented by an element named 'remote-domain'. The domain name of the peer in an optional attribute named 'name'. Optionally, each actual (e.g. TCP) connection from the local server to the peer is added as a 'connection' child-element to the 'remote-domain' element, that has an optional 'type' attribute, defining the directionality of the connection (one of 'incoming', 'outgoing' and 'bidi').</p>
<p>The name of a remote domain MUST only be included if the remote server advertises support for this XEP. This acts as an opt-in mechanism, to address the privacy concern defined in the <link url="#privacy">Privacy Considerations section</link> of this document.</p>
<example caption="Data Format with Federated Domains"><![CDATA[
<serverinfo xmlns="urn:xmpp:serverinfo:0">
<domain name="shakespeare.lit">
<federation>
<remote-domain name='denmark.lit'>
<connection type="incoming"/>
<connection type="outgoing"/>
</remote-domain>
<remote-domain name='montague.net'>
<connection type="bidi"/>
</remote-domain>
</federation>
</domain>
</serverinfo>]]></example>
<p>Additional data MAY be included as child-elements of the 'serverinfo' element or any of the 'domain' elements. Such data MUST be namespaced appropriately. The example below uses the 'query' element defined in &xep0092; to include information about the software application associated with the local server.</p>
<example caption="Data Format with Software Version"><![CDATA[
<serverinfo xmlns="urn:xmpp:serverinfo:0">
<domain name="shakespeare.lit">
<federation>
<remote-domain name='montague.net'>
<connection type="bidi"/>
</remote-domain>
</federation>
</domain>
<query xmlns='jabber:iq:version'>
<name>Openfire</name>
<version>4.8.0</version>
<os>Windows 11</os>
</query>
</serverinfo>]]></example>
</section1>
<section1 topic="Publication" anchor="impl">
<p>The data is to be published using a pub-sub node named 'serverinfo' that MUST be a first-level leaf node of a pub-sub service for the domain. It is RECOMMENDED that the leaf-node is configured to have an open access model and contain a maximum of 1 item.</p>
<example caption="Publish ServerInfo Item"><![CDATA[
<iq type='set'
from='william@shakespeare.lit/atwork'
to='pubsub.shakespeare.lit'
id='publish1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='serverinfo'>
<item id='current'>
<serverinfo xmlns="urn:xmpp:serverinfo:0">
<domain name="shakespeare.lit">
<federation>
<remote-domain name='denmark.lit'>
<connection type="incoming"/>
<connection type="outgoing"/>
</remote-domain>
<remote-domain name='montague.net'>
<connection type="bidi"/>
</remote-domain>
</federation>
</domain>
</serverinfo>
</item>
</publish>
</pubsub>
</iq>]]></example>
</section1>
<section1 topic="Implementation Notes" anchor="impl">
<p>As certain information can be expected to be updated continuously and frequently, the server MAY choose to reduce the frequency of updates of the 'serverinfo' pub-sub node.</p>
</section1>
<section1 topic="Privacy Considerations" anchor="privacy">
<p>When multiple domains publish their connections to named remote domains, an information leak occurs: by collecting these public statistics, behavioral data of those remote domains can be deduced. To prevent undesired privacy-sensitive information leaks, a domain MUST NOT publish the name of a remote domain, unless that domain advertises support for this XEP, as defined in the <link url="#disco">Discovering Support section</link> of this document.</p>
<p>This way, the service discovery mechanism doubles as an opt-in mechanism. Domains that advertise support for this XEP allow other domains to reference them by domain-name in the data that they publish. The mere presence of an applicable pub-sub node MUST NOT be used for Service Discovery purposes, as under common service configuration, non-administrative users are allowed to create such nodes.</p>
</section1>
<section1 topic="XMPP Registrar Considerations" anchor="registrar">
<p>Upon advancement of this specification from a status of Experimental to a status of Draft, the &REGISTRAR; shall include the following information in its registries.</p>
<section2 topic="Protocol Namespaces" anchor="registrar-ns">
<p>This specification defines the following XML namespaces:</p>
<ul>
<li>urn:xmpp:serverinfo:0</li>
</ul>
<p>The &REGISTRAR; shall add the foregoing namespace to the registry located at &NAMESPACES;, as described in Section 4 of &xep0053;.</p>
</section2>
<section2 topic='Field Standardization' anchor='registrar-formtype'>
<p>&xep0068; defines a process for standardizing the fields used within Data Forms qualified by a particular namespace, and <cite>XEP-0128</cite> describes how to use field standardization in the context of service discovery. This section registers fields for server information scoped by the "http://jabber.org/network/serverinfo" FORM_TYPE.</p>
<code caption='Registry Submission'><![CDATA[
<form_type>
<name>http://jabber.org/network/serverinfo</name>
<doc>XEP-0XXX</doc>
<desc>
Forms advertising the coordinates of a pub-sub service and node for publication of Server Information data.
</desc>
<field
var='serverinfo-pubsub-node'
type='text-single'
label='An URI (per XEP-0060 section 12.22) identifying the pub-sub node on which Server Information data is published.'/>
</form_type>
]]></code>
<p>Note that the FORM_TYPE used by &xep0157; is purposefully re-used by this XEP, to circumvent the restriction of having at most one XMPP Standards Foundation defined FORM_TYPE for a service discovery identity, as defined in &xep0128;. When a service supports both features, the data in both forms SHOULD be merged into one form.</p>
</section2>
</section1>
<section1 topic='XML Schema' anchor='schema'>
<code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:xmpp:serverinfo:0'
xmlns='urn:xmpp:serverinfo:0'
elementFormDefault='qualified'>
<xs:annotation>
<xs:documentation>
The protocol documented by this schema is defined in
XEP-0XXX: http://www.xmpp.org/extensions/xep-0XXX.html
</xs:documentation>
</xs:annotation>
<xs:element name="serverinfo" type="urn:serverinfoType" xmlns:urn="urn:xmpp:serverinfo:0"/>
<xs:simpleType name="directionType" final="restriction" >
<xs:restriction base="xs:string">
<xs:enumeration value="incoming" />
<xs:enumeration value="outgoing" />
<xs:enumeration value="bidi" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="connectionType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="directionType" name="type" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="remote-domainType">
<xs:sequence>
<xs:element type="urn:connectionType" name="connection" maxOccurs="unbounded" minOccurs="0" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="optional"/>
</xs:complexType>
<xs:complexType name="federationType">
<xs:sequence>
<xs:element type="urn:remote-domainType" name="remote-domain" maxOccurs="unbounded" minOccurs="0" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="domainType">
<xs:sequence>
<xs:element type="urn:federationType" name="federation" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name"/>
</xs:complexType>
<xs:complexType name="serverinfoType">
<xs:sequence>
<xs:element type="urn:domainType" name="domain" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
]]></code>
</section1>
<section1 topic='Acknowledgements' anchor='acknowledgements'>
<p>Inspiration was taken from the (now defunct) 'server info' crawler by Thomas Leister. Many thanks to Dave Cridland, as well as 'zoidberg' and 'chewie' from the Ignite Realtime community for helping to test the initial implementation of a graphing implementation based on this XEP and to Florian Schmaus, Matthew Wild, Jonas Schäfer and Kevin Smith for their feedback on the earliest drafts of this document.</p>
</section1>
</xep>

231
inbox/xep-mds.xml Normal file
View File

@ -0,0 +1,231 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Message Displayed Synchronization</title>
<abstract>This specification allows multiple clients of the same user to synchronize the displayed state of their chats.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0001</spec>
<spec>Etc.</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>mds</shortname>
<author>
<firstname>Daniel</firstname>
<surname>Gultsch</surname>
<email>daniel@gultsch.de</email>
<jid>daniel@gultsch.de</jid>
</author>
<revision>
<version>0.0.1</version>
<date>2024-02-21</date>
<initials>dg</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>In multi-device environments marking a chat as <em>displayed</em> on one device should mark that chat as <em>displayed</em> on all devices. Historically carbon copies (&xep0280;) of the &lt;displayed/> element of Chat Markers (&xep0333;) have been used to achieve this effect. However this approach has a couple of downsides that this specification is trying eliminate:</p>
<ul>
<li>The contact has to request Chat Markers by tagging a message with &lt;markable/>.</li>
<li>Chat Markers let the contact know that a device has displayed the message. This might not always be advisable when synchronization across multiple devices of the same user is the desired outcome.</li>
<li>When used in large group chats Chat Markers can create a lot of unwanted traffic.</li>
</ul>
<p>This specification isolates the task of multi-device synchronization from providing information to the contact, while borrowing some of the semantics of Chat Markers such as <em>displayed</em> refering to all messages up to this point.</p>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<ul>
<li>Basic functionality should not depend on server features that go beyond what is commonly implemented at the time of writing this specification.</li>
<li>Rely on server-injected &lt;stanza-id/> (see &xep0359;) to provide unique and stable IDs. While this is commonly done as part of &xep0313; it does not technically depend on the message being archived.</li>
<li>Define the interaction with &xep0333;.</li>
<li>Provide optional methods for traffic optimizations on supporting servers.</li>
<li>Make no assertions on what constitutes an <em>open</em> or <em>archived</em> chat. This specification allows clients to state that they have displayed messages in a certain chat up to a certain point. It does not indicate that a chat is open or in case of group chats joined.</li>
</ul>
</section1>
<section1 topic='Glossary' anchor='glossary'>
<dl>
<di>
<dt>Displayed</dt>
<dd>
Colloquially this is also known as <em>read</em>. However since a common implementation of <em>read</em> is: "shown on screen, in full, in the context of the chat", and this gives no indication on whether the user has actually read a message, <em>displayed</em> was chosen as a more accurate terminology. A message might also be manually acknowledged by the user, for example via a <em>mark as read</em> action in a notification. Implementations are also possible, for example in smart home devices or infotainment systems, where the message is read aloud by a Text-to-Speech system, but never actually displayed. It is up to the implementors discretion to determine what the best approximation of <em>the user has had a reasonable chance to mentally process the message</em> is.
</dd>
</di>
</dl>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic="Server-side persistence" anchor='pep-node'>
<p>Clients use items in a private PEP (&xep0163;) node called 'urn:xmpp:mds:displayed:0' to synchronize and persist the displayed state (See &xep0223;). The item ID corresponds to the JID of the respective chat. For normal, 1:1 chats this SHOULD be the bare JID of the contact, for group chats this SHOULD be the bare JID of the room and for private messages in group chats the full JID of the participant.</p>
<p>The item contains a single &lt;displayed/> element qualified by the 'xrn:xmpp:mds:displayed:0' namespace. The &lt;displayed/> element MUST contain exactly one &xep0359; &lt;stanza-id/> element that corresponds to the stanza-id of the most recent, displayed message, in that particular chat.</p>
</section2>
<section2 topic="Flagging chat as displayed" anchor='publish'>
<p>Only messages <strong>received</strong> by the user (meaning sent by third parties such as a contact, a participant in a group chat, etc) SHOULD be flagged as 'displayed'. However since 'displayed' means <em>all messages up to this point</em> and the stanza-id of a message <strong>sent</strong> by the user indicates a valid point in the chat history, sent messages MAY be flagged as well.</p>
<p>Flagging a chat as <em>displayed up to this point</em> happens by publishing a PEP item with an id corresponding to the JID of the chat and a &lt;displayed/> payload element into the 'urn:xmpp:mds:displayed:0' node.</p>
<p>For group chats the &lt;stanza-id/> child of the &lt;displayed/> element refers to the stanza-id injected by the room. For all other chats the stanza-id child refers to the stanza-id injected by the users server (the server hosting the user account).</p>
<p>The client MUST include appropriate publish-options in the publication, including, but not limited to, setting the access model to whitelist and the max-items to max.</p>
<example caption='Client marks a chat as display'><![CDATA[
<iq from='juliet@capulet.lit/balcony' type='set' id='flag-as-displayed-1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:mds:displayed:0'>
<item id='romeo@montegue.lit'>
<displayed xmlns='urn:xmpp:mds:displayed:0'>
<stanza-id xmlns='urn:xmpp:sid:0'
by='juliet@capulet.lit'
id='0f710f2b-52ed-4d52-b928-784dad74a52b'/>
</display>
</item>
</publish>
<publish-options>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#publish-options</value>
</field>
<field var='pubsub#persist_items'>
<value>true</value>
</field>
<field var='pubsub#max_items'>
<value>max</value>
</field>
<field var='pubsub#send_last_published_item'>
<value>never</value>
</field>
<field var='pubsub#access_model'>
<value>whitelist</value>
</field>
</x>
</publish-options>
</pubsub>
</iq>
]]></example>
<example caption="Server acknowledges successful storage"><![CDATA[
<iq to='juliet@capulet.lit/balcony' type='result' id='flag-as-displayed-1'/>
]]></example>
</section2>
<section2 topic="Retrieving notifications" anchor="notify">
<p>A client interested in synchronizing the displayed state with other clients SHOULD include the 'urn:xmpp:mds:displayed:0+notify' feature in its &xep0115;, as per &xep0163; rules.</p>
</section2>
<section2 topic="Catching up" anchor="catchup">
<p>Upon bind and initial presence a client retrieves all items in the 'urn:xmpp:mds:displayed:0' node to learn what changes to the displayed state have occured while the client was offline.</p>
<example caption="Client retrieves all displayed items"><![CDATA[
<iq from='juliet@capulet.lit/balcony' type='get' id='catchup-1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='urn:xmpp:mds:displayed:0'/>
</pubsub>
</iq>
]]></example>
<example caption="Server returns the displayed states for various chat"><![CDATA[
<iq type='result'
to='juliet@capulet.lit/balcony'
id='catchup-1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='urn:xmpp:mds:displayed:0'>
<item id='romeo@montegue.lit'>
<displayed xmlns='urn:xmpp:mds:displayed:0'>
<stanza-id xmlns='urn:xmpp:sid:0'
id='0f710f2b-52ed-4d52-b928-784dad74a52b'
by='juliet@capulet.lit'/>
</displayed>
</item>
<item id='example@conference.shakespeare.lit'>
<displayed xmlns='urn:xmpp:mds:displayed:0'
<stanza-id xmlns='urn:xmpp:sid:0'
id='ca21deaf-812c-48f1-8f16-339a674f2864'
by='example@conference.shakespeare.lit'/>
</displayed>
</item>
</items>
</pubsub>
</iq>
]]></example>
</section2>
<section2 topic="Interaction with Chat Markers and Server Assist" anchor="interaction">
<p>A &xep0333; displayed marker refers to the message id set by the sender of the message whereas the displayed element defined in this specification refers to the stanza-id injected by the users server.</p>
<p>In the likely scenario that a client wishes to share the displayed state with their own devices and the sender of the message, a client SHOULD sent a &xep0333; displayed marker and ensure that the 'urn:xmpp:mds:displayed:0' node gets updated.</p>
<section3 topic="Server assist">
<p>A &xep0060; item publication is a fairly verbose operation for something that is expected to happen rather frequently. Therfore this specification defines an optional way to combine the PEP node item update and the Chat Marker in one simple message.</p>
</section3>
<section3 topic="Discovering support">
<p>Server assisted displayed node updates are an optional feature a users server can provide. To signal support the server announces an &xep0115; feature of 'urn:xmpp:mds:server-assist:0' on the account.</p>
<example caption="Client queries for server features"><![CDATA[
<iq type='get' id='disco-1' to='juliet@capulet.lit' from='juliet@capulet.lit/balcony'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption="Server responds with features"><![CDATA[
<iq type='result' id='disco1' from='juliet@capulet.lit' to='juliet@capulet.lit/balcony'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<feature var='urn:xmpp:mds:server-assist:0'/>
</query>
</iq>
]]></example>
</section3>
<section3 topic="Sending assisted displayed">
<p>To update the displayed item in the 'urn:xmpp:mds:displayed:0' PEP node more efficiently a client MAY send a message with the 'to' attribute set to the item id (which is equivalent to the JID of the contact) and with a &lt;displayed/> element qualified by the 'urn:xmpp:mds:displayed:0' namespace. The server MUST strip the &lt;displayed/> element from the message and continue to process it normally. The server MUST publish a PEP item on the 'urn:xmpp:mds:displayed:0' node where the item id is taken from the 'to' attribute and the payload is the &lt;displayed/> element. A client MUST NOT include the &lt;displayed/> element qualified by the 'urn:xmpp:mds:displayed:0' namespace if the message would otherwise be empty. A client that wishes to update the device synchronized displayed state but not inform the sender of the message via Chat Markers SHOULD use the regular PubSub publication process.</p>
<example caption="Romeo sends a message to Juliet"><![CDATA[
<message to='juliet@capulet.lit' from='romeo@montegue.lit/orchard' id='the-msg-1'>
<body>Hi. How are you?</body>
<markable xmlns='urn:xmpp:chat-markers:0'/>
<stanza-id xmlns='urn:xmpp:sid:0' by='juliet@capulet.lit' id='0423e3a9-d516-493d-bb06-bee0e51ab9fb'/>
</message>
]]></example>
<example caption="Juliet lets both Romeo and her other devices know she has displayed the message"><![CDATA[
<message to='romeo@montegue.lit' from='juliet@capulet.let/balcony'>
<displayed xmlns='urn:xmpp:chat-markers:0' id='the-msg-1'/>
<displayed xmlns='urn:xmpp:mds:displayed:0'>
<stanza-id xmlns='urn:xmpp:sid:0' by='juliet@capulet.lit' id='0423e3a9-d516-493d-bb06-bee0e51ab9fb'/>
</displayed>
</message>
]]></example>
<example caption="Server sends out PEP notifications to Juliets connected devices"><![CDATA[
<message from='juliet@capulet.lit' to='juliet@capulet.lit/balcony' type='headline' id='new-displayed-pep-event'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='urn:xmpp:mds:displayed:0'>
<item id='romeo@montegue.lit'>
<displayed xmlns='urn:xmpp:mds:displayed:0'>
<stanza-id xmlns='urn:xmpp:sid:0' by='juliet@capulet.lit' id='0423e3a9-d516-493d-bb06-bee0e51ab9fb'/>
</displayed>
</item>
</items>
</event>
</message>
]]></example>
</section3>
</section2>
</section1>
<section1 topic='Business Rules' anchor='rules'>
<ul>
<li>The displayed state only moves forward. Receiving a displayed state with a stanza-id that references a message older than the current local representation is considered redundant and MUST be ignored.</li>
<li>Displayed states with a stanza-id not found in the respective chat MUST be ignored.</li>
<li>Receiving an outgoing message (for example via &xep0280; or &xep0313;) SHOULD NOT mark the chat as displayed. Outgoing messages are neutral towards the overall displayed state of a given chat. For example if the <em>displayed up to</em> state references the most recent incoming message and this message is only followed by outgoing messages the overall state of that chat SHOULD be considered <em>displayed</em>.</li>
<li>A client receiving an outgoing message MAY NOT update the displayed node item with that stanza-id. However clients SHOULD be able to handle displayed states that use stanza-ids that refer to outgoing messages and simply consider the chat as displayed up to that point.</li>
<li>While Chat Markers (&xep0333;), in 1:1 chats, MAY be sent to a full JID, a client combining both &lt;displayed/> elements in a single message MUST address that message to the bare JID, as the server will use the verbatim 'to' attribute as the item ID.</li>
</ul>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<ul>
<li>When publishing displayed states via &xep0060; the client MUST use publish-options to set the access model on the node to <em>whitelist</em>. To ensure the server supports publish-options the client MUST first check for the "http://jabber.org/protocol/pubsub#publish-options" feature.</li>
<li>Servers that support the server assist feature MUST strip the &lt;displayed/> element in the "urn:xmpp:mds:displayed:0" namespace from the message to avoid the stanza-id being leaked to the recipient of that message.</li>
<li>Clients MUST NOT put the &lt;displayed/> into a message to trigger server-assited displayed synchronization unless the server announces the "urn:xmpp:mds:server-assist:0" feature.</li>
<li>This specification provides a convenient process to synchronize a users own devices and informing the third party in one, single message. However letting the third party know is not always desirable, for example when the user has generally opted out of transmitting the displayed status or when a non-contact initiated a chat. In those cases the client MUST use the &xep0060; method instead of server-assist.</li>
</ul>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>REQUIRED.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>REQUIRED.</p>
</section1>
<section1 topic='XML Schema' anchor='schema'>
<p>REQUIRED for protocol specifications.</p>
</section1>
</xep>

View File

@ -13,6 +13,7 @@
<status>Active</status>
<type>Informational</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>RFC 6120</spec>
<spec>XEP-0050</spec>
@ -21,6 +22,12 @@
<supersededby/>
<shortname>admin</shortname>
&stpeter;
<revision>
<version>1.3.0</version>
<date>2024-01-04</date>
<initials>gdk</initials>
<remark>Removed use case 'Get User Password', which violates best-practices with regard to security.</remark>
</revision>
<revision>
<version>1.2</version>
<date>2017-07-15</date>
@ -110,7 +117,7 @@
<li>Disable User</li>
<li>Re-Enable User</li>
<li>End User Session</li>
<li>Get User Password</li>
<li>Get User Password (retracted)</li>
<li>Change User Password</li>
<li>Get User Roster</li>
<li>Get User Last Login Time</li>
@ -539,92 +546,8 @@
</iq>
]]></example>
</section2>
<section2 topic='Get User Password' anchor='get-user-password'>
<p>An administrator may need to retrieve a user's password. The command node for this use case SHOULD be "http://jabber.org/protocol/admin#get-user-password".</p>
<p>A sample protocol flow for this use case is shown below.</p>
<example caption='Admin Requests to Get a User&apos;s Password'><![CDATA[
<iq from='bard@shakespeare.lit/globe'
id='get-user-password-1'
to='shakespeare.lit'
type='set'
xml:lang='en'>
<command xmlns='http://jabber.org/protocol/commands'
action='execute'
node='http://jabber.org/protocol/admin#get-user-password'/>
</iq>
]]></example>
<p>Unless an error occurs (see the <link url='#errors'>Error Handling</link> section below), the service SHOULD return the appropriate form.</p>
<example caption='Service Returns Get User Password Form to Admin'><![CDATA[
<iq from='shakespeare.lit'
id='get-user-password-1'
to='bard@shakespeare.lit/globe'
type='result'
xml:lang='en'>
<command xmlns='http://jabber.org/protocol/commands'
node='http://jabber.org/protocol/admin#get-user-password'
sessionid='get-user-password:20040408T0337Z'
status='executing'>
<x xmlns='jabber:x:data' type='form'>
<title>Getting a User's Password</title>
<instructions>Fill out this form to get a user&apos;s password.</instructions>
<field type='hidden' var='FORM_TYPE'>
<value>http://jabber.org/protocol/admin</value>
</field>
<field label='The Jabber ID for which to retrieve the password'
type='jid-single'
var='accountjid'>
<required/>
</field>
</x>
</command>
</iq>
]]></example>
<p>Note: If the entity is an end user, the JID SHOULD be of the form &lt;user@host&gt;, not &lt;user@host/resource&gt;.</p>
<example caption='Admin Submits Get User Password Form to Service'><![CDATA[
<iq from='bard@shakespeare.lit/globe'
id='get-user-password-2'
to='shakespeare.lit'
type='set'
xml:lang='en'>
<command xmlns='http://jabber.org/protocol/commands'
node='http://jabber.org/protocol/admin#get-user-password'
sessionid='get-user-password:20040408T0337Z'>
<x xmlns='jabber:x:data' type='submit'>
<field type='hidden' var='FORM_TYPE'>
<value>http://jabber.org/protocol/admin</value>
</field>
<field var='accountjid'>
<value>juliet@shakespeare.lit</value>
</field>
</x>
</command>
</iq>
]]></example>
<p>Naturally, the data form included in the IQ result will include the user's password.</p>
<example caption='Service Informs Admin of Completion'><![CDATA[
<iq from='shakespeare.lit'
id='get-user-password-2'
to='bard@shakespeare.lit/globe'
type='result'
xml:lang='en'>
<command xmlns='http://jabber.org/protocol/commands'
node='http://jabber.org/protocol/admin#get-user-password'
sessionid='get-user-password:20040408T0337Z'
status='completed'>
<x xmlns='jabber:x:data' type='result'>
<field type='hidden' var='FORM_TYPE'>
<value>http://jabber.org/protocol/admin</value>
</field>
<field var='accountjid'>
<value>juliet@shakespeare.lit</value>
</field>
<field var='password'>
<value>R0m30</value>
</field>
</x>
</command>
</iq>
]]></example>
<section2 topic='Get User Password (retracted)' anchor='get-user-password'>
<p>Up to and including revision 1.2 of this XEP, this section defined a command that could be used to retrieve a user's password. This implies that the implementation stores plaintext passwords, a practise that is a well-documented vulnerability<note>OWASP: Password Plaintext Storage &lt;<link url='https://owasp.org/www-community/vulnerabilities/Password_Plaintext_Storage'>https://owasp.org/www-community/vulnerabilities/Password_Plaintext_Storage</link>&gt;</note>. This command has therefore been retracted from this XEP. To retain section numbering, this text replaces the command definition that previously existed in this section.</p>
</section2>
<section2 topic='Change User Password' anchor='change-user-password'>
<p>An administrator may need to change a user's password. The command node for this use case SHOULD be "http://jabber.org/protocol/admin#change-user-password".</p>

View File

@ -12,7 +12,7 @@
</abstract>
&LEGALNOTICE;
<number>0458</number>
<status>Experimental</status>
<status>Active</status>
<type>Procedural</type>
<sig>None</sig>
<approver>Board</approver>
@ -22,6 +22,12 @@
<shortname>N/A</shortname>
&dcridland;
&stpeter;
<revision>
<version>1.0.0</version>
<date>2024-01-15</date>
<initials>psa</initials>
<remark><p>Changed status to Active per Board vote on 2024-01-05.</p></remark>
</revision>
<revision>
<version>0.4.0</version>
<date>2023-12-11</date>

View File

@ -29,7 +29,17 @@
<surname>der Kinderen</surname>
<email>guus.der.kinderen@gmail.com</email>
<jid>guus.der.kinderen@igniterealtime.org</jid>
</author>
</author>
<revision>
<version>0.2.0</version>
<date>2023-12-12</date>
<initials>do</initials>
<remark>
<ul>
<li>Use XEP-0482 to send the meeting link to another party</li>
</ul>
</remark>
</revision>
<revision>
<version>0.1.0</version>
<date>2023-12-11</date>
@ -38,6 +48,7 @@
<ul>
<li>Promoted to Experimental.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.3</version>
@ -84,9 +95,23 @@
</revision>
</header>
<section1 topic="Introduction" anchor="intro">
<p>XMPP protocol extensions already defines a method for initiating peer-to-peer media sessions such as &xep0166; however due to its very nature of being peer-to-peer it does not work very well in scenarios with online meetings. It also does not work alongside offline storage, MUC history and &xep0313;.</p>
<p>Using a web browser to manually request a URL from an HTTP server and sharing the link has been a workaround for this for a long time now. While users have a variety of services to choose from, the downside of this manual approach is that an XMPP client can not automate this process on behalf of the user since these services dont share a common API.</p>
<p>This XEP defines an approach to request initiation of an online meeting via an HTTP server and receive a URL can be used to join and invite others to the meeting.</p>
<p>XMPP protocol extensions already defines a method for initiating peer-to-peer media sessions such as &xep0166; however due to its very nature of being peer-to-peer it presents a few challenges in scenarios with online meetings that depend on a central Selective Forwarding Unit (SFU) or a Multipoint Control Unit (MCU) to host the meeting..</p>
<p>Using a web browser to manually request a meeting URL from an HTTP server and sharing the link has been a workaround for this for a long time now. While users have a variety of services to choose from, the downside of this manual approach is that an XMPP client can not automate this process on behalf of the user since these services dont share a common API.</p>
<p>This XEP defines an approach to request initiation of an online meeting via an HTTP server and receive a URL can be used to join and invite others to the meeting. It has two main features:</p>
<ol>
<li>An IQ-based protocol to request a meeting link from a server.</li>
<li>An element that can be added to a message stanza for sending the received meeting link to another party</li>
</ol>
<p>
The second feature is achieved by using &xep0482;, which describes
call invites using Jingle and external URIs. The XEP mentions how a web URLs can be used as external URI to join a call. For completeness, an example is repeated here to explicitly show how meeting invitations should be sent to invitees.
</p>
<p>
&xep0482; has other call mangement features, like announcing call join and
leave on the XMPP side. These are relevant for online meetings when the website behind the URL is opened
in a frame or similar inside the XMPP client. The meeting host xmpp client can track meeting participants and know when users leave the meeting without having to depend on APIs provided by the meeting service provider which may present cross-domain challenges.
For completeness, examples are also repeated in this XEP to explicity show their application for online meeting invitations.
</p>
</section1>
<section1 topic="Requirements" anchor="reqs">
<ul>
@ -178,23 +203,26 @@
<query xmlns='urn:xmpp:http:online-meetings:0'
type='jitsi'>
<desc>Meeting room for Open Standards discussion</desc>
</query>
</iq>]]></example>
<p>The XMPP server responds with one or two child elements: a 'initiate' element that contains a URL to be used to create and configure the meeting, and an 'invite' element that contains a URL suitable to invite others into the meeting.</p>
<p>The XMPP server responds with one or two child elements: a 'initiate' element that contains a URL to be used to create and configure the meeting, and an 'invite' element as specified by &xep0482; to invite others into the meeting.</p>
<p>In the URLs that it returns, the server MAY specify a web-based protocol handler if available and registered by the user. Otherwise, standard HTTPS protocol will be specified. In any case, the fully resolved URL provided by the host MUST provide Transport Layer Security (&rfc5246;). The HTTPS URL MUST adhere to &rfc3986;. Non ASCII characters MUST be percent-encoded.</p>
<example caption="The server responds with an out of band URI specifying the jitsi web-based protocol handler"><![CDATA[
<example caption="The server responds with an out of band URI specifying a registered jitsi web-based protocol handler"><![CDATA[
<iq from='montague.tld'
to='romeo@montague.tld/garden'
id='initiate_03'
type='result'>
<query xmlns='urn:xmpp:http:online-meetings:0'>
<initiate type='jitsi'>
<url>web+jitsi:https://meet.jit.si/OpenStandardsMuchGreatness</url>
<url>web+jitsi:OpenStandardsMuchGreatness</url>
<desc>Meeting room for Open Standards discussion</desc>
</initiate>
<invite type='jitsi'>
<url>web+jitsi:https://meet.jit.si/OpenStandardsMuchGreatness</url>
<desc>Meeting room for Open Standards discussion</desc>
</invite>
<invite xmlns='urn:xmpp:call-invites:0'>
<external uri='web+jitsi:OpenStandardsMuchGreatness' />
<meeting xmlns='urn:xmpp:http:online-meetings:0'
type='jitsi'
desc='Meeting room for Open Standards discussion' />
</invite>
</query>
</iq>]]></example>
<example caption="The server responds with an out of band URI using standard HTTPS"><![CDATA[
@ -207,10 +235,12 @@
<url>https://meet.jit.si/OpenStandardsMuchGreatness</url>
<desc>Meeting room for Open Standards discussion</desc>
</initiate>
<invite type='jitsi'>
<url>https://meet.jit.si/OpenStandardsMuchGreatness</url>
<desc>Meeting room for Open Standards discussion</desc>
</invite>
<invite xmlns='urn:xmpp:call-invites:0'>
<external uri='https://meet.jit.si/OpenStandardsMuchGreatness' />
<meeting xmlns='urn:xmpp:http:online-meetings:0'
type='jitsi'
desc='Meeting room for Open Standards discussion' />
</invite>
</query>
</iq>]]></example>
<p>The XMPP server MAY be tightly integrated with the Meeting Provider and facilitate registration, configuration and association of a web-based protocol handler, but the protocol to implement such integration is out of scope of this document.</p>
@ -272,25 +302,82 @@
</iq>]]></example>
</section1>
<section1 topic="Meeting Invitation" anchor="meeting-invitation">
<p>After the requesting entity has successfully initiated a meeting, it MAY invite other entities to join the meeting. It does so by sending invitees a message stanza containing an 'invite' child element, qualified by the online-meetings namespace, as was sent by the server in response to the initiation request.</p>
<p>To allow users of clients that do not support this XEP to receive the invitation, a &xep0066; element and/or a 'body' element containing the meeting details MAY be included.</p>
<example caption="User sends meeting invitation"><![CDATA[
<p>After the requesting entity has successfully initiated a meeting, it MAY invite other entities to join the meeting using the 'invite' element it received to propose the meeting</p>
<p>To allow users of clients that do not support &xep0482; to receive the invitation, a &xep0066; element and/or a 'body' element containing the meeting details MAY be included.</p>
<p>There is no further XMPP communication required between the server and the requesting entity for participants to join the meeting. The actual online meeting engagement with the provided URL is out of scope of this document.</p>
<section2 topic="Proposing a meeting" anchor="meeting-proposal">
<p>
Invitees are sent a message containing an &lt;invite&gt; element in the urn:xmpp:call-invites:0
namespace. For online meetings, the audio video attributes should default to "true".
</p><p>
The &lt;invite&gt; element contains sub-elements &lt;external&gt; and &lt;meeting&gt; to provide the meeting URL and the identity of the meeting service provider.
</p> <example caption="User sends meeting invitation"><![CDATA[
<message
id='invite_01'
from='romeo@montague.tld/garden'
to='juliet@capulet.example/balcony'>
<invite xmlns='urn:xmpp:http:online-meetings:0'
type='jitsi'>
<url>https://meet.jit.si/OpenStandardsMuchGreatness</url>
<desc>Meeting room for Open Standards discussion</desc>
</invite>
<invite xmlns='urn:xmpp:call-invites:0'>
<external uri='https://meet.jit.si/OpenStandardsMuchGreatness' />
<meeting xmlns='urn:xmpp:http:online-meetings:0'
type='jitsi'
desc='Meeting room for Open Standards discussion' />
</invite>
<x xmlns='jabber:x:oob'>
<url>https://meet.jit.si/OpenStandardsMuchGreatness</url>
<desc>Meeting room for Open Standards discussion</desc>
</x>
<body>You are invited to join 'Meeting room for Open Standards discussion' at https://meet.jit.si/OpenStandardsMuchGreatness</body>
</message>]]></example>
<p>There is no further XMPP communication required between the server and the client for the client to join the meeting. The actual online meeting engagement with the provided URL is out of scope of this document.</p>
</section1>
</section2>
<section2 topic="Retracting a meeting invitation" anchor="meeting-retraction">
<p>
A meeting invitation can be retracted by sending a message containing a &lt;retract&gt; element with an 'id' attribute
containing the id of the invite message qualified by the urn:xmpp:call-invites:0 namespace.
</p>
<example caption="Retracting a meeting"><![CDATA[
<message to='juliet@capulet.example/balcony'>
<retract id='invite_01' xmlns='urn:xmpp:call-invites:0' />
</message>]]></example>
</section2>
<section2 topic="Accepting a meeting invitation" anchor="meeting-acceptance">
<p>
A meeting invitation can be accepted by sending a message containing an &lt;accept&gt; element with an 'id' attribute
containing the id of the invite message and qualified by the urn:xmpp:call-invites:0 namespace.
The &lt;external&gt; and &lt;meeting&gt; elements from the invitation are placed in the &lt;accept&gt; element as specified in &xep0482;.
</p>
<example caption="Accepting a meeting invitation"><![CDATA[
<message to='romeo@montague.tld/garden'>
<accept id='invite_01' xmlns='urn:xmpp:call-invites:0'>
<external uri='https://meet.jit.si/OpenStandardsMuchGreatness' />
<meeting type='jitsi' desc='Meeting room for Open Standards discussion' />
</accept>
</message>]]></example>
<p>
After the &lt;accept&gt; was sent, the accepting client handles the URI. The exact behaviour of opening the URI is implementation specific and can be determined from the type attribute of the &lt;meeting&gt; element.
</p>
</section2>
<section2 topic="Rejection a meeting invitation" anchor="meeting-rejection">
<p>
A meeting invitation can be rejected by sending a message containing a &lt;reject&gt; element with an 'id' attribute
containing the id of the invite message and qualified by the urn:xmpp:call-invites:0 namespace.
</p>
<example caption="Rejecting a meeting invitation"><![CDATA[
<message to='romeo@montague.tld/garden'>
<reject id='invite_01' xmlns='urn:xmpp:call-invites:0' />
</message>]]></example>
</section2>
<section2 topic="Leaving a meeting" anchor="meeting-exit">
<p>
When a meeting participant leaves a meeting, it sends a message containing a &lt;left&gt; element with an 'id' attribute
containing the id of the invite message and qualified by the urn:xmpp:call-invites:0 namespace.
</p>
<example caption="Leaving a meeting"><![CDATA[
<message to='romeo@montague.tld/garden'>
<left id='invite_01' xmlns='urn:xmpp:call-invites:0' />
</message>]]></example>
</section2>
</section1>
<section1 topic="Implementation Notes" anchor="impl">
<p>The server SHOULD choose an appropriate timeout for the validity of the URL. Since there is no reason for a client to wait between requesting the URL and joining the meeting via the URL before dispatching invitations, relatively low timeout values of around 300s are RECOMMENDED.</p>
</section1>

View File

@ -31,7 +31,8 @@
<ul>
<li>Promoted to Experimental.</li>
</ul>
</revision>
</remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2022-10-19</date>

278
xep-0485.xml Normal file
View File

@ -0,0 +1,278 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM '../xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep xmlns="">
<header>
<title>PubSub Server Information</title>
<abstract>This document defines a data format whereby basic information of an XMPP domain can be expressed and exposed over pub-sub.</abstract>
&LEGALNOTICE;
<number>0485</number>
<status>Experimental</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies/>
<supersedes/>
<supersededby/>
<shortname>serverinfo</shortname>
<author>
<firstname>Guus</firstname>
<surname>der Kinderen</surname>
<email>guus.der.kinderen@gmail.com</email>
<jid>guus.der.kinderen@igniterealtime.org</jid>
</author>
<revision>
<version>0.1.0</version>
<date>2024-03-10</date>
<initials>dg</initials>
<remark>
<ul>
<li>Promoted to Experimental.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2023-12-19</date>
<initials>gdk</initials>
<remark>
<ul>
<li>Initial version.</li>
</ul>
</remark>
</revision>
</header>
<section1 topic="Introduction" anchor="intro">
<p>To facilitate discovery of information of individual domains in an XMPP-based network, this specification defines a data format to define basic information for individual XMPP domains. By leveraging &xep0060; this information can efficiently be shared with applications that compose an overview of the larger XMPP network.</p>
</section1>
<section1 topic="Requirements" anchor="requirements">
<ul>
<li>Describe links between nodes in an XMPP-based network, by enumerating connections used for federation between XMPP domains.</li>
<li>An extensible data format, allowing additional data (such as that defined in &xep0092;) to be retrievable without requiring additional round-trips.</li>
</ul>
</section1>
<section1 topic="Discovering Support" anchor="disco">
<p>Domains supporting the publication of Server Information data, as described in this document, MUST advertise the fact by announcing a &xep0030; feature of 'urn:xmpp:serverinfo:0'. This signifies that an administrative entity approved the publication of data, which is important for the opt-in mechanism described in <link url="#privacy">Privacy Considerations section</link> of this document.</p>
<p>The pub-sub service address and node in which Server Information data is advertised SHOULD be specified using a &xep0128;, using an URI as specified in section 12.22 of XEP-0060. These pub-sub coordinates MUST be scoped using a FORM_TYPE of "http://jabber.org/network/serverinfo" (as specified in XEP-0157) and data form field registered for this purpose as defined in the <link url="#registrar">XMPP Registrar Considerations section</link> of this document.</p>
<p>When the 'urn:xmpp:serverinfo:0' feature but no corresponding Service Discovery Extension is advertised, the node that is used will be a first-level leaf node using the name 'serverinfo' on the first pub-sub service advertised through service discovery.</p>
<example caption="Service Discovery information request"><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='shakespeare.lit'
id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]></example>
<example caption="Service Discovery information response"><![CDATA[
<iq type='result'
from='shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='urn:xmpp:serverinfo:0'/>
...
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/network/serverinfo</value>
</field>
<field var='serverinfo-pubsub-node'>
<value>xmpp:pubsub.shakespeare.lit?;node=serverinfo</value>
</field>
</x>
</query>
</iq>]]></example>
<p>The node MUST reference a first-level leaf node on a pub-sub service.</p>
<example caption="Entity queries root node for information"><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='info1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='serverinfo'/>
</iq>]]></example>
<example caption="Service responds with identity of pubsub/leaf"><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='info1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='serverinfo'>
...
<identity category='pubsub' type='leaf'/>
...
</query>
</iq>]]></example>
</section1>
<section1 topic="Data Format" anchor="impl">
<p>The data format uses an element named 'serverinfo' in the namespace 'urn:xmpp:serverinfo:0'. In its minimal form, it defines each XMPP domain name served by the local server in an attribute named 'name'.</p>
<example caption="Minimal Data Format"><![CDATA[
<serverinfo xmlns='urn:xmpp:serverinfo:0'>
<domain name='shakespeare.lit'/>
</serverinfo>]]></example>
<p>The optional 'federation' child element is used to denote remote XMPP domains with which the local domain is federating. Each of them are represented by an element named 'remote-domain'. The domain name of the peer in an optional attribute named 'name'. Optionally, each actual (e.g. TCP) connection from the local server to the peer is added as a 'connection' child-element to the 'remote-domain' element, that has an optional 'type' attribute, defining the directionality of the connection (one of 'incoming', 'outgoing' and 'bidi').</p>
<p>The name of a remote domain MUST only be included if the remote server advertises support for this XEP. This acts as an opt-in mechanism, to address the privacy concern defined in the <link url="#privacy">Privacy Considerations section</link> of this document.</p>
<example caption="Data Format with Federated Domains"><![CDATA[
<serverinfo xmlns="urn:xmpp:serverinfo:0">
<domain name="shakespeare.lit">
<federation>
<remote-domain name='denmark.lit'>
<connection type="incoming"/>
<connection type="outgoing"/>
</remote-domain>
<remote-domain name='montague.net'>
<connection type="bidi"/>
</remote-domain>
</federation>
</domain>
</serverinfo>]]></example>
<p>Additional data MAY be included as child-elements of the 'serverinfo' element or any of the 'domain' elements. Such data MUST be namespaced appropriately. The example below uses the 'query' element defined in &xep0092; to include information about the software application associated with the local server.</p>
<example caption="Data Format with Software Version"><![CDATA[
<serverinfo xmlns="urn:xmpp:serverinfo:0">
<domain name="shakespeare.lit">
<federation>
<remote-domain name='montague.net'>
<connection type="bidi"/>
</remote-domain>
</federation>
</domain>
<query xmlns='jabber:iq:version'>
<name>Openfire</name>
<version>4.8.0</version>
<os>Windows 11</os>
</query>
</serverinfo>]]></example>
</section1>
<section1 topic="Publication" anchor="impl">
<p>The data is to be published using a pub-sub node named 'serverinfo' that MUST be a first-level leaf node of a pub-sub service for the domain. It is RECOMMENDED that the leaf-node is configured to have an open access model and contain a maximum of 1 item.</p>
<example caption="Publish ServerInfo Item"><![CDATA[
<iq type='set'
from='william@shakespeare.lit/atwork'
to='pubsub.shakespeare.lit'
id='publish1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='serverinfo'>
<item id='current'>
<serverinfo xmlns="urn:xmpp:serverinfo:0">
<domain name="shakespeare.lit">
<federation>
<remote-domain name='denmark.lit'>
<connection type="incoming"/>
<connection type="outgoing"/>
</remote-domain>
<remote-domain name='montague.net'>
<connection type="bidi"/>
</remote-domain>
</federation>
</domain>
</serverinfo>
</item>
</publish>
</pubsub>
</iq>]]></example>
</section1>
<section1 topic="Implementation Notes" anchor="impl">
<p>As certain information can be expected to be updated continuously and frequently, the server MAY choose to reduce the frequency of updates of the 'serverinfo' pub-sub node.</p>
</section1>
<section1 topic="Privacy Considerations" anchor="privacy">
<p>When multiple domains publish their connections to named remote domains, an information leak occurs: by collecting these public statistics, behavioral data of those remote domains can be deduced. To prevent undesired privacy-sensitive information leaks, a domain MUST NOT publish the name of a remote domain, unless that domain advertises support for this XEP, as defined in the <link url="#disco">Discovering Support section</link> of this document.</p>
<p>This way, the service discovery mechanism doubles as an opt-in mechanism. Domains that advertise support for this XEP allow other domains to reference them by domain-name in the data that they publish. The mere presence of an applicable pub-sub node MUST NOT be used for Service Discovery purposes, as under common service configuration, non-administrative users are allowed to create such nodes.</p>
</section1>
<section1 topic="XMPP Registrar Considerations" anchor="registrar">
<p>Upon advancement of this specification from a status of Experimental to a status of Draft, the &REGISTRAR; shall include the following information in its registries.</p>
<section2 topic="Protocol Namespaces" anchor="registrar-ns">
<p>This specification defines the following XML namespaces:</p>
<ul>
<li>urn:xmpp:serverinfo:0</li>
</ul>
<p>The &REGISTRAR; shall add the foregoing namespace to the registry located at &NAMESPACES;, as described in Section 4 of &xep0053;.</p>
</section2>
<section2 topic='Field Standardization' anchor='registrar-formtype'>
<p>&xep0068; defines a process for standardizing the fields used within Data Forms qualified by a particular namespace, and <cite>XEP-0128</cite> describes how to use field standardization in the context of service discovery. This section registers fields for server information scoped by the "http://jabber.org/network/serverinfo" FORM_TYPE.</p>
<code caption='Registry Submission'><![CDATA[
<form_type>
<name>http://jabber.org/network/serverinfo</name>
<doc>XEP-0XXX</doc>
<desc>
Forms advertising the coordinates of a pub-sub service and node for publication of Server Information data.
</desc>
<field
var='serverinfo-pubsub-node'
type='text-single'
label='An URI (per XEP-0060 section 12.22) identifying the pub-sub node on which Server Information data is published.'/>
</form_type>
]]></code>
<p>Note that the FORM_TYPE used by &xep0157; is purposefully re-used by this XEP, to circumvent the restriction of having at most one XMPP Standards Foundation defined FORM_TYPE for a service discovery identity, as defined in &xep0128;. When a service supports both features, the data in both forms SHOULD be merged into one form.</p>
</section2>
</section1>
<section1 topic='XML Schema' anchor='schema'>
<code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:xmpp:serverinfo:0'
xmlns='urn:xmpp:serverinfo:0'
elementFormDefault='qualified'>
<xs:annotation>
<xs:documentation>
The protocol documented by this schema is defined in
XEP-0XXX: http://www.xmpp.org/extensions/xep-0XXX.html
</xs:documentation>
</xs:annotation>
<xs:element name="serverinfo" type="urn:serverinfoType" xmlns:urn="urn:xmpp:serverinfo:0"/>
<xs:simpleType name="directionType" final="restriction" >
<xs:restriction base="xs:string">
<xs:enumeration value="incoming" />
<xs:enumeration value="outgoing" />
<xs:enumeration value="bidi" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="connectionType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="directionType" name="type" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="remote-domainType">
<xs:sequence>
<xs:element type="urn:connectionType" name="connection" maxOccurs="unbounded" minOccurs="0" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="optional"/>
</xs:complexType>
<xs:complexType name="federationType">
<xs:sequence>
<xs:element type="urn:remote-domainType" name="remote-domain" maxOccurs="unbounded" minOccurs="0" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="domainType">
<xs:sequence>
<xs:element type="urn:federationType" name="federation" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name"/>
</xs:complexType>
<xs:complexType name="serverinfoType">
<xs:sequence>
<xs:element type="urn:domainType" name="domain" xmlns:urn="urn:xmpp:serverinfo:0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
]]></code>
</section1>
<section1 topic='Acknowledgements' anchor='acknowledgements'>
<p>Inspiration was taken from the (now defunct) 'server info' crawler by Thomas Leister. Many thanks to Dave Cridland, as well as 'zoidberg' and 'chewie' from the Ignite Realtime community for helping to test the initial implementation of a graphing implementation based on this XEP and to Florian Schmaus, Matthew Wild, Jonas Schäfer and Kevin Smith for their feedback on the earliest drafts of this document.</p>
</section1>
</xep>

323
xep-0486.xml Normal file
View File

@ -0,0 +1,323 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>MUC Avatars</title>
<abstract>This specification describes how to publish and retrieve avatars in rooms.</abstract>
&LEGALNOTICE;
<number>0486</number>
<status>Experimental</status>
<type>Historical</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0030</spec>
<spec>XEP-0045</spec>
<spec>XEP-0054</spec>
<spec>XEP-0068</spec>
<spec>XEP-0153</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
&linkmauve;
<revision>
<version>0.1.0</version>
<date>2024-03-10</date>
<initials>XEP Editor: dg</initials>
<remark>
<ul>
<li>Promoted to Experimental</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.3</version>
<date>2023-02-15</date>
<initials>egp</initials>
<remark><p>Restore to the first revision, and republish to the Historical track.</p></remark>
</revision>
<revision>
<version>0.0.2</version>
<date>2018-11-03</date>
<initials>tj</initials>
<remark><p>Generalise to non-MUC resources.</p></remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2018-08-21</date>
<initials>egp</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>Avatars are small images people often use to identify each other very quickly in chat applications. They are well defined for users, in &xep0084; and &xep0153;, but until now chat rooms all shared a default icon. This extension provides a way for owners to associates an avatar to their chat room, and for users to discover that an avatar is associated and display it accordingly.</p>
<p>XMPP services have traditionally allowed owners to <link url='https://docs.ejabberd.im/tutorials/muc-vcard/'>set a vCard-temp on a MUC</link> using &xep0054;, this extension tries to keep as much of it as possible so existing applications dont have to be modified too much.</p>
<p>Some implementations recently chose to advertise those avatars using the existing &xep0153; extension in &lt;presence/&gt;, but it exposed issues in other implementations, and was only available when the user is already present in the room, not before joining it (for example when listing all available rooms).</p>
<p>A future extension superseding this one could define a method based on &xep0084;, with a PubSub service on the rooms bare JID containing the metadata and data nodes. Such a specification should also define a compatibility profile similar to &xep0398; for user avatars, enabling the coexistence of both versions until the present one is deemed obsolete.</p>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>This specification SHOULD:</p>
<ul>
<li>Allow authorised entities to set an avatar on a MUC.</li>
<li>Allow authorised entities to remove a previously-set avatar on a MUC.</li>
<li>Allow users to discover an avatar is set on a MUC.</li>
<li>Allow users to request the avatar of a MUC.</li>
<li>Let users know that the avatar of a MUC changed while they are present in said MUC.</li>
<li>Let users discover the avatar even when not present in the MUC.</li>
<li>Stay as compatible as possible with the current usage of avatars in MUC.</li>
</ul>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic='Discover the features supported by a service' anchor='disco'>
<p>Before trying to use avatars, a client must check that the group chat service hosting a room does support them.</p>
<example caption='Users client discovers the features of a MUC service'><![CDATA[
<iq type='get'
id='p87Ne'
from='romeo@montague.example.net/garden'
to='chat.shakespeare.example.org'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]></example>
<example caption='Room advertises support for vcard-temp'><![CDATA[
<iq type='result'
id='p87Ne'
to='romeo@montague.example.net/garden'
from='chat.shakespeare.example.org'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
type='text'
name='Shakespearean Chat Service'/>
<feature var='http://jabber.org/protocol/muc'/>
<feature var='vcard-temp'/>
...
</query>
</iq>]]></example>
</section2>
<section2 topic='Owner of the Room Publishes Avatar' anchor='owner-publish'>
<p>Before anyone can see an avatar attached to the room, an owner or some other priviledged entity must publish a vCard-temp containing the avatars data, using the protocol defined in &xep0054;.</p>
<example caption='Owners client publishes avatar to the room'><![CDATA[
<iq type='set'
id='7fP13'
from='romeo@montague.example.net/garden'
to='garden@chat.shakespeare.example.org'>
<vCard xmlns='vcard-temp'>
<PHOTO>
<TYPE>image/svg+xml</TYPE>
<BINVAL>PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+CiA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9InJlZCIvPgo8L3N2Zz4K</BINVAL>
</PHOTO>
</vCard>
</iq>]]></example>
<example caption='Room acknowledges publish action'><![CDATA[
<iq type='result'
id='7fP13'
to='romeo@montague.example.net/garden'
from='garden@chat.shakespeare.example.org'/>]]></example>
<p>There is no other action required on the owners end.</p>
<p>If the room doesnt support support avatars, it must return a service-unavailable error.</p>
<example caption='Room doesnt support vCard-temp'><![CDATA[
<iq type='error'
id='7fP13'
to='romeo@montague.example.net/garden'
from='garden@chat.shakespeare.example.org'>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>]]></example>
<p>If the user trying to publish an avatar isnt allowed to do so, the room must return a forbidden error, see the <link url='#security'>Security Considerations</link>.</p>
<example caption='User is not allowed to set vCard-temp'><![CDATA[
<iq type='error'
id='7fP13'
to='romeo@montague.example.net/garden'
from='garden@chat.shakespeare.example.org'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text>Only owners are allowed to set avatars.</text>
</error>
</iq>]]></example>
<p>The room should then broadcast a notification that the configuration changed to all users present.</p>
<example caption='Room broadcasts a configuration change'><![CDATA[
<message type='groupchat'
to='romeo@montague.example.net/garden'
from='garden@chat.shakespeare.example.org'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<status code='104'/>
</x>
</message>
<message type='groupchat'
to='juliet@capulet.example.com/balcony'
from='garden@chat.shakespeare.example.org'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<status code='104'/>
</x>
</message>]]></example>
<p>Setting an empty vCard unpublishes the avatar.</p>
<example caption='Owners client removes a rooms avatar'><![CDATA[
<iq type='set'
id='83tFs'
from='romeo@montague.example.net/garden'
to='garden@chat.shakespeare.example.org'>
<vCard xmlns='vcard-temp'/>
</iq>]]></example>
</section2>
<section2 topic='User Discovers the Avatar' anchor='disco-avatar-hash'>
<p>At any point, whether it is during a join in order to display it in its UI, after having discovered the list of the rooms and to list them with additional information, or when receiving a &lt;status code='104'/&gt; configuration change notification, a users client can discover information about a room.</p>
<example caption='Users client discovers information about a room'><![CDATA[
<iq type='get'
id='K92am'
from='juliet@capulet.example.com/balcony'
to='garden@chat.shakespeare.example.org'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]></example>
<p>If the room has had <link url='#owner-publish'>an avatar published</link>, it should advertise it in its 'muc#roominfo' extension form, using the &xep0153; hash computation method.</p>
<example caption='Room advertises its avatar hash'><![CDATA[
<iq type='result'
id='K92am'
to='juliet@capulet.example.com/balcony'
from='garden@chat.shakespeare.example.org'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
type='text'
name='The Garden'/>
<feature var='http://jabber.org/protocol/muc'/>
<feature var='vcard-temp'/>
...
<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_avatarhash'
type='text-multi'
label='Avatar hash'>
<value>a31c4bd04de69663cfd7f424a8453f4674da37ff</value>
</field>
...
</x>
</query>
</iq>]]></example>
<p>This 'muc#roominfo_avatarhash' will not be present when the room doesnt have an avatar set.</p>
</section2>
<section2 topic='User Retrieves the vCard' anchor='retrieve-vcard'>
<p>At this point the client knows the hash and can retrieve the rooms vCard-temp.</p>
<example caption='Users client retrieves the vCard-temp'><![CDATA[
<iq type='get'
id='uD10h'
from='juliet@capulet.example.com/balcony'
to='garden@chat.shakespeare.example.org'>
<vCard xmlns='vcard-temp'/>
</iq>]]></example>
<example caption='Room returns the vCard-temp containing the avatar'><![CDATA[
<iq type='result'
id='uD10h'
to='juliet@capulet.example.com/balcony'
from='garden@chat.shakespeare.example.org'>
<vCard xmlns='vcard-temp'>
<PHOTO>
<TYPE>image/svg+xml</TYPE>
<BINVAL>PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+CiA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9InJlZCIvPgo8L3N2Zz4K</BINVAL>
</PHOTO>
</vCard>
</iq>]]></example>
<p>The client then has to decode the &lt;BINVAL/&gt; content from base64, hash it with sha1 and compare it with the advertised hash, and if it matches uses it as the room avatar under the &lt;TYPE/&gt; media type.</p>
</section2>
</section1>
<section1 topic='Business Rules' anchor='rules'>
<p>An application MUST support the image/png media type, SHOULD support image/jpeg, image/gif and image/svg+xml, and MAY support additional formats.</p>
<p>A room SHOULD NOT include a 'muc#roominfo_avatarhash' field if it doesnt have an avatar set.</p>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<section2 topic='Multiple Stored Version of an Avatar' anchor='multiple'>
<p>Multiple &lt;PHOTO/&gt; elements may be present in a vCard, in which case they should all represent the same image and the 'muc#roominfo_avatarhash' field must contain a hash of all of them.</p>
<example caption='Owners client publishes avatar in two different formats'><![CDATA[
<iq type='set'
id='7fP13'
from='romeo@montague.example.net/garden'
to='garden@chat.shakespeare.example.org'>
<vCard xmlns='vcard-temp'>
<PHOTO>
<TYPE>image/svg+xml</TYPE>
<BINVAL>PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+CiA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9InJlZCIvPgo8L3N2Zz4K</BINVAL>
</PHOTO>
<PHOTO>
<TYPE>image/png</TYPE>
<BINVAL>iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAB3RJTUUH4ggVERoVAPsrMgAAAAlwSFlzAAALEgAACxIB0t1+/AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAEZ0FNQQAAsY8L/GEFAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGUExURf8AAP///0EdNBEAAAABYktHRAH/Ai3eAAAADElEQVQI12NgGNwAAACgAAFhJX1HAAAAAElFTkSuQmCC</BINVAL>
</PHOTO>
</vCard>
</iq>]]></example>
<example caption='Room advertises both hashes'><![CDATA[
<iq type='result'
id='K92am'
to='juliet@capulet.example.com/balcony'
from='garden@chat.shakespeare.example.org'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
type='text'
name='The Garden'/>
<feature var='http://jabber.org/protocol/muc'/>
<feature var='vcard-temp'/>
...
<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_avatarhash'
type='text-multi'
label='Avatar hash'>
<value>a31c4bd04de69663cfd7f424a8453f4674da37ff</value>
<value>b9b256f999ded52c2fa14fb007c2e5b979450cbb</value>
</field>
...
</x>
</query>
</iq>]]></example>
</section2>
<section2 topic='Previous Usage of Presence for Avatar Advertising' anchor='presence'>
<p>Some existing implementations send or expect a presence from the rooms bare JID in order to detect an avatar being published. This had several issues, with existing clients handling that as a presence from a user with an empty nick or downright triggering an error, and was only available if the client was already present in the room, preventing any usecase where it would get displayed before entering the room.</p>
<p>For those reasons, this XEP doesnt encourage this way of advertising the presence of an avatar, but for reference it would look like a &xep0153; presence payload:</p>
<example caption='Room advertises a non-standard vCard update in a presence'><![CDATA[
<presence from='garden@chat.shakespeare.example.org'>
<x xmlns='vcard-temp:x:update'>
<photo>a31c4bd04de69663cfd7f424a8453f4674da37ff</photo>
</x>
</presence>
]]></example>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>A server should take care that only allowed entities can publish a vCard-temp on a MUC, for instance room owners or service administrators.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<section2 topic='Field Standartization' anchor='registrar-formtype'>
<p>The registrar shall add the following field to the 'muc#roominfo' data form:</p>
<section3 topic='muc#roominfo FORM_TYPE' anchor='registrar-formtype-roominfo'>
<code caption='Registry Submission'><![CDATA[
<form_type>
<name>http://jabber.org/protocol/muc#roominfo</name>
<doc>XEP-XXXX</doc>
<desc>Form extension for avatar support in a Multi-User Chat (MUC) room.</desc>
<field
var='muc#roominfo_avatarhash'
type='text-multi'
label='Hash of the vCard-temp avatar of this room'/>
</form_type>
]]></code>
</section3>
</section2>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>Thanks to the Ejabberd developers for their MUC vCard tutorial, and to Sam Whited and Matthew Wild for their feedback.</p>
</section1>
</xep>

View File

@ -57,7 +57,7 @@
<p>OPTIONAL.</p>
</section1>
<section1 topic='Accessibility Considerations' anchor='access'>
<p>OPTIONAL.</p>
<p>REQUIRED.</p>
</section1>
<section1 topic='Internationalization Considerations' anchor='i18n'>
<p>OPTIONAL.</p>
@ -65,6 +65,9 @@
<section1 topic='Security Considerations' anchor='security'>
<p>REQUIRED.</p>
</section1>
<section1 topic='Privacy Considerations' anchor='privacy'>
<p>REQUIRED.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>REQUIRED.</p>
</section1>

View File

@ -1689,4 +1689,7 @@ IANA Service Location Protocol, Version 2 (SLPv2) Templates</link></span> <note>
<!ENTITY xep0480 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0480.html'>SASL Upgrade Tasks (XEP-0480)</link></span><note>XEP-0480: SASL Upgrade Tasks &lt;<link url='https://xmpp.org/extensions/xep-0480.html'>https://xmpp.org/extensions/xep-0480.html</link>&gt;.</note>">
<!ENTITY xep0481 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0481.html'>Content Types in Messages (XEP-0481)</link></span><note>XEP-0481: Content Types in Messages &lt;<link url='https://xmpp.org/extensions/xep-0481.html'>https://xmpp.org/extensions/xep-0481.html</link>&gt;.</note>">
<!ENTITY xep0482 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0482.html'>Call Invites (XEP-0482)</link></span><note>XEP-0482: Call Invites &lt;<link url='https://xmpp.org/extensions/xep-0482.html'>https://xmpp.org/extensions/xep-0482.html</link>&gt;.</note>">
<!ENTITY xep0483 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0483.html'>HTTP Online Meetings (XEP-0483)</link></span><note>XEP-0483: HTTP Online Meetings &lt;<link url='https://xmpp.org/extensions/xep-0483.html'>https://xmpp.org/extensions/xep-0483.html</link>&gt;.</note>"><!ENTITY xep0484 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0484.html'>Fast Authentication Streamlining Tokens (XEP-0484)</link></span><note>XEP-0484: Fast Authentication Streamlining Tokens &lt;<link url='https://xmpp.org/extensions/xep-0484.html'>https://xmpp.org/extensions/xep-0484.html</link>&gt;.</note>">
<!ENTITY xep0483 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0483.html'>HTTP Online Meetings (XEP-0483)</link></span><note>XEP-0483: HTTP Online Meetings &lt;<link url='https://xmpp.org/extensions/xep-0483.html'>https://xmpp.org/extensions/xep-0483.html</link>&gt;.</note>">
<!ENTITY xep0484 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0484.html'>Fast Authentication Streamlining Tokens (XEP-0484)</link></span><note>XEP-0484: Fast Authentication Streamlining Tokens &lt;<link url='https://xmpp.org/extensions/xep-0484.html'>https://xmpp.org/extensions/xep-0484.html</link>&gt;.</note>">
<!ENTITY xep0485 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0485.html'>PubSub Server Information (XEP-0485)</link></span><note>XEP-0485: PubSub Server Information &lt;<link url='https://xmpp.org/extensions/xep-0485.html'>https://xmpp.org/extensions/xep-0485.html</link>&gt;.</note>">
<!ENTITY xep0486 "<span class='ref'><link url='https://xmpp.org/extensions/xep-0486.html'>MUC Avatars (XEP-0486)</link></span><note>XEP-0486: MUC Avatars &lt;<link url='https://xmpp.org/extensions/xep-0486.html'>https://xmpp.org/extensions/xep-0486.html</link>&gt;.</note>">

View File

@ -257,7 +257,10 @@ content: "XEP-<xsl:value-of select='/xep/header/number'/>";
</ul></dd>
</xsl:if>
<dt>Copyright</dt>
<dd>&#169; 1999 &#x2013; 2021 XMPP Standards Foundation. <a href='#appendix-legal'>SEE LEGAL NOTICES</a>.</dd>
<!-- Extract the copyright years from the dates via
substring(). If we ever use XSL 2.0, then we could use
year-from-date(xs:date()) -->
<dd>&#169; <xsl:value-of select='substring(/xep/header/revision[position()=last()]/date,1,4)'/> &#x2013; <xsl:value-of select='substring(/xep/header/revision[position()=1]/date,1,4)'/> XMPP Standards Foundation. <a href='#appendix-legal'>SEE LEGAL NOTICES</a>.</dd>
<dt>Status</dt>
<dd>
<p><xsl:choose>
@ -531,7 +534,9 @@ content: "XEP-<xsl:value-of select='/xep/header/number'/>";
<xsl:variable name="bibtex-url">
<xsl:choose>
<!-- XEPs after a certain number have an immutable version to which we preferably link -->
<xsl:when test='/xep/header/number &gt; 300'>
<!-- TODO: We currently have no versioned link for the latest version of a XEP,
hence the logic below is disabled for all XEPs, by testing for XEP version number > 99999 -->
<xsl:when test='/xep/header/number &gt; 999999'>
<xsl:text>https://xmpp.org/extensions/attic/xep-</xsl:text>
<xsl:value-of select='/xep/header/number'/>
<xsl:text>-</xsl:text>