Merge branch 'master' into xep300-cdata

This commit is contained in:
Florian Schmaus 2017-10-04 16:11:13 +02:00
commit 4b37098d47
129 changed files with 10484 additions and 1736 deletions

View File

@ -4,10 +4,13 @@
FROM xmppxsf/xeps-base:latest
ARG NCORES=1
ARG TARGETS="html pdf"
ARG TARGETS="html inbox-html inbox-xml pdf xeplist"
COPY *.xml xep.* *.css *.xsl *.js *.xsl Makefile /src/
COPY resources/*.pdf /src/resources/
COPY tools/*.py /src/tools/
COPY inbox/*.xml inbox/*.ent inbox/*.dtd /src/inbox/
COPY texml-xsl/*.xsl /src/texml-xsl/
WORKDIR /src
RUN OUTDIR=/var/www/html/extensions/ make -j$NCORES $TARGETS

View File

@ -7,11 +7,34 @@ XMLDEPS=xep.xsd xep.ent xep.dtd ref.xsl $(OUTDIR)
TEXMLDEPS=xep2texml.xsl $(OUTDIR)/xmpp.pdf $(OUTDIR)/xmpp-text.pdf
XEPDIRS=. inbox
HTMLDEPS=xep.xsl $(CSSTARGETS) $(JSTARGETS)
CSSTARGETS=$(OUTDIR)/xmpp.css $(OUTDIR)/prettify.css
JSTARGETS=$(OUTDIR)/prettify.js
base_CSSTARGETS=xmpp.css prettify.css
CSSTARGETS=$(addprefix $(OUTDIR)/,$(base_CSSTARGETS))
proto_CSSTARGETS=$(addprefix $(OUTDIR)/inbox/,$(base_CSSTARGETS))
base_JSTARGETS=prettify.js
JSTARGETS=$(addprefix $(OUTDIR)/,$(base_JSTARGETS))
proto_JSTARGETS=$(addprefix $(OUTDIR)/inbox/,$(base_JSTARGETS))
proto_HTMLDEPS=xep.xsl $(proto_CSSTARGETS) $(proto_JSTARGETS)
DO_XELATEX=cd $(OUTDIR); xelatex --interaction=nonstopmode -no-shell-escape "$(notdir $(basename $@)).tex" >/dev/null
xeps=$(wildcard *.xml)
proto_xeps=$(wildcard inbox/*.xml)
all_xeps=$(xeps) $(proto_xeps)
xep_xmls=$(patsubst %.xml,$(OUTDIR)/%.xml,$(xeps))
proto_xep_xmls=$(patsubst %.xml,$(OUTDIR)/%.xml,$(proto_xeps))
all_xep_xmls=$(xep_xmls) $(proto_xep_xmls)
xep_htmls=$(patsubst %.xml,$(OUTDIR)/%.html,$(xeps))
proto_xep_htmls=$(patsubst %.xml,$(OUTDIR)/%.html,$(proto_xeps))
all_xep_htmls=$(xep_htmls) $(proto_xep_htmls)
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))
.PHONY: help
help:
@ -33,17 +56,29 @@ help:
.PHONY: all
all: html
.PHONY: xeplist
xeplist: $(OUTDIR)/xeplist.xml
.PHONY: html
html: $(patsubst %.xml, $(OUTDIR)/%.html, $(wildcard *.xml))
html: $(xep_htmls)
.PHONY: xml
xml: $(xep_xmls)
.PHONY: inbox-html
inbox-html: $(proto_xep_htmls)
.PHONY: inbox-xml
inbox-xml: $(proto_xep_xmls)
.PHONY: pdf
pdf: $(patsubst %.xml, $(OUTDIR)/%.pdf, $(wildcard *.xml))
pdf: $(xep_pdfs)
.PHONY: refs
refs: $(patsubst xep-%.xml, $(REFSDIR)/reference.XSF.XEP-%.xml, $(wildcard *.xml))
refs: $(xep_refs)
.PHONY: examples
examples: $(patsubst xep-%.xml, $(EXAMPLESDIR)/%.xml, $(wildcard *.xml))
examples: $(xep_examples)
.PHONY: xep-%
xep-%: $(OUTDIR)/xep-%.html $(REFSDIR)/reference.XSF.XEP-%.xml $(OUTDIR)/xep-%.pdf $(EXAMPLESDIR)/%.xml;
@ -54,19 +89,33 @@ xep-%.html: $(OUTDIR)/xep-%.html ;
.PHONY: xep-%.pdf
xep-%.pdf: $(OUTDIR)/xep-%.pdf ;
$(all_xep_xmls): $(OUTDIR)/%.xml: %.xml
cp $< $@
$(OUTDIR)/xeplist.xml: $(wildcard *.xml) $(wildcard inbox/*.xml)
./tools/extract-metadata.py > $@
$(EXAMPLESDIR)/%.xml: xep-%.xml $(XMLDEPS) examples.xsl $(EXAMPLESDIR)
xsltproc --path $(CURDIR) examples.xsl "$<" > "$@" && echo "Finished building $@"
$(REFSDIR)/reference.XSF.XEP-%.xml: xep-%.xml $(XMLDEPS) ref.xsl $(REFSDIR)
xsltproc --path $(CURDIR) ref.xsl "$<" > "$@" && echo "Finished building $@"
$(OUTDIR)/%.html: %.xml $(XMLDEPS) $(HTMLDEPS)
$(xep_htmls): $(OUTDIR)/xep-%.html: xep-%.xml $(XMLDEPS) $(HTMLDEPS)
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) xep.xsl "$<" > "$@" && echo "Finished building $@"
xsltproc --path $(CURDIR) --param htmlbase "$(if $(findstring inbox,$<),'../','./')" xep.xsl "$<" > "$@" && echo "Finished building $@"
$(proto_xep_htmls): $(OUTDIR)/inbox/%.html: inbox/%.xml $(XMLDEPS) $(proto_HTMLDEPS)
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 $@)" "$@"
@ -92,7 +141,13 @@ $(JSTARGETS): $(OUTDIR)
$(CSSTARGETS): $(OUTDIR)
cp "$(notdir $@)" "$@"
$(EXAMPLESDIR) $(REFSDIR) $(OUTDIR):
$(proto_JSTARGETS): $(OUTDIR)/inbox
cp "$(notdir $@)" "$@"
$(proto_CSSTARGETS): $(OUTDIR)/inbox
cp "$(notdir $@)" "$@"
$(EXAMPLESDIR) $(REFSDIR) $(OUTDIR) $(OUTDIR)/inbox:
mkdir -p "$@"
.PHONY: clean

363
README.md
View File

@ -1,4 +1,5 @@
[![Docker Build Status](https://img.shields.io/docker/build/xmppxsf/xeps.svg)](https://hub.docker.com/r/xmppxsf/xeps/)
[![Build Status](https://img.shields.io/travis/xsf/xeps.svg)](https://travis-ci.org/xsf/xeps)
XMPP Extension Protocols (XEPs)
=========
@ -50,4 +51,364 @@ For more information try `make help`.
Using Docker
------------
A full set of HTML and PDFs can be generated inside a docker container, with no dependencies on the host other than Docker itself, and served by nginx in the container. To build the template `make docker`, to run it `make testdocker` (serves on http://localhost:3080), and to stop/delete it afterwards `make stopdocker`
A full set of HTML and PDFs can be generated inside a docker container, with no
dependencies on the host other than Docker itself, and served by nginx in the
container. To build the template `make docker`, to run it `make testdocker`
(serves on http://localhost:3080), and to stop/delete it afterwards `make
stopdocker`
Gardening (Issue triaging by non-editors)
-----------------------------------------
For new PRs, anyone with permission may perform gardening tasks.
The [Go wiki] sumarizes "gardening" as:
> the background maintenance tasks done to keep the project healthy & growing &
> nice looking.
In this repo, gardening is mostly triaging issues.
An issue is considered triaged when an editor has been assigned to it.
Untriaged issues that are in need of attention can be found using the following
filter: [`is:open is:pr no:assignee`]
To triage new issues or PRs:
- Is the issue a duplicate? Close it (referencing the original issue).
- Is the issue a question and not an issue? Close it, pointing them at the
mailing list or chat room.
- Is the PR a new ProtoXEP? Add the "[ProtoXEP]" label and ensure that the
file is in the "inbox/" tree and does not start with "xep-" (if not, leave a
comment asking for it to be moved).
- Is the issue a specific change to an existing XEP or a few XEPs (eg. not
whitespace changes to many XEPs, use your judgement)? Make sure the title
starts with "XEP-XXXX:" or "XEP-XXXX, XEP-YYYY:".
- Finally, assign an editor (pick one at random, or pick the one with the least
issues already assigned to them; we may re-assign it later so don't feel bad).
The list of active editors can be found here:
https://xmpp.org/about/xsf/editor-team
Editor
======
The XMPP Extensions Editor (or, for short, XEP Editor) manages the XMPP
extensions process as defined in XMPP Extension Protocols ([XEP-0001]).
In addition, the XEP Editor functions as the XMPP Registrar as defined in XMPP
Registrar Function ([XEP-0053]).
Read those documents first, since this README focuses on mechanics instead of
philosophy or policy.
All PRs
-------
For all PRs, start by ensuring that the IP release has been signed and that CI
has run and no issues were detected before merging.
Triaging a PR
-------------
If the PR is not touching a XEP, this guide does not apply. If the PR touches
multiple XEPs, go through the steps for each XEP and exit at the first which
applies.
1. Is the PR a ProtoXEP?
1. Does the PR touch existing XEPs? Close as [invalid] and ask the Opener
to split the two things.
2. Add the [ProtoXEP] and [Ready to Merge] labels.
3. Stop.
1. Are the changes *for all XEPs* purely editorial?
1. Add the [Editorial Change] and [Ready to Merge] labels.
2. Stop.
2. Is the XEP **not** in Experimental state?
(Changes to Non—Experimental XEPs need approval by the approving body as
defined in the XEP file itself.)
1. Add the [Needs Council]/[Needs Board] label.
2. Put the PR in the [Council Trello] project.
3. Stop.
2. Is the XEP in Experimental state and the PR opener is not an author of the
XEP?
1. If the issue has not been discussed on the standards list *or* if
the authors have not been involved in the discussion:
1. Make sure the standards@ discussion (if it exists) is linked in the
PR.
2. Add the [Needs Author] label.
3. Put the PR in the [Editor Trello] project.
4. Stop.
3. Mark the PR as [Ready to Merge].
Discussions
-----------
Technical discussions SHOULD NOT happen in the xeps repository. If you see a
discussion evolve into technical (as opposed to editorial) matters, do the
following (I havent tried that myself yet, so feel especially free to improve
the process):
1. Lock the conversation.
2. Copy the technical discussion parts into an email to standards@. My
preferred format for this would be something along the lines of:
Subject: XEP-1234: [insert PR subject here, or something more appropriate]
There was some discussion on the xeps repository an XEP-1234, which got
technical. I moved this discussion to standards@ so that the whole
community is aware of the issue and can participate.
@user1 wrote:
> quote user1 here ...
@user2 wrote:
> quote user2 here ...
Remove clearly editorial discussion and mark the removal with ``[…]``.
3. Add the [Needs List Discussion] label to the PR and link the standards@
thread you just created. Remove other labels (such as [Needs Author]).
4. Monitor the thread; when the discussion is resolved, the PR opener will
usually prepare an update. Unlock the conversation to allow editorial
discussion to continue, if needed. Remove the [Needs List Discussion] label
and re-triage the PR as described above.
**Note:** The locking is mostly used here as a tool to avoid a race
condition, not to exclude people from participating. (It would be
unfortunate if you had to add more comments to your already-sent email.)
Feel free to unlock at some point during the list discussion when youre
sure that all participants have taken note of the move.
General notes on making changes
-------------------------------
This section has some hints on the python scripts which help you doing the
more tedious tasks of sending emails and properly archiving XEPs.
*Before* you start working on merging a Pull Request:
* Ideally, you have the [xep-attic] repository cloned next to the xeps
repository.
* Before starting to prepare a merge and push, ensure that you have the XEP
metadata up-to-date locally:
$ make build/xeplist.xml
* Make a copy of the metadata:
$ cp build/xeplist.xml tools/old-xeplist.xml
(avoid putting random XML files in the xeps root directory, the build
tooling might mistake them as XEPs; so we put it somewhere else.)
*While* youre working on a Pull Request:
* Use the lokal docker build to ensure that everything is syntactically
correct. The process is described above in "Using Docker".
When you have *merged* the Pull Request and the change went through to the
webserver (see also the [Docker Build] to track the build progress):
* Send out the emails. First ensure that the new metadata is up-to-date:
$ make build/xeplist.xml
Check that the emails which will be sent are correct (the ``--dry-run``
switch prevents the tool from actually sending emails):
$ ./tools/send-updates.py --dry-run tools/old-xeplist.xml build/xeplist.xml standards@xmpp.org
(See also the ``--help`` output for more information.)
Once youve verified that the correct emails will be sent, actually send
them using (note the missing ``--dry-run`` flag):
$ ./tools/send-updates.py tools/old-xeplist.xml build/xeplist.xml standards@xmpp.org
A few tips:
1. You can also test-send them to your own address by replacing
``standards@xmpp.org`` with your own address.
2. To avoid having to enter your email account details every time, use a
configuration file. Invoke the tool with ``--help`` for more
information and ask [jonasw]/[@horazont] if things are still unclear.
If the tool misbehaves, pester [jonasw]/[@horazont] about it.
* Dont forget to archive the new versions of the XEPs. If you have the
[xep-attic] cloned next to the xeps repository, you can simply run:
$ ./tools/archive.py tools/old-xeplist.xml build/xeplist.xml
Otherwise, you will have to explicitly give the path to the attic:
$ ./tools/archive.py --attic /path/to/xep-attic/content/ tools/old-xeplist.xml build/xeplist.xml
(note that the path must point to the ``content`` subdirectory of the
[xep-attic].)
Dont forget to commit & push the changes to [xep-attic].
New ProtoXEPs
-------------
- Make sure the protoxep is in the `inbox/` tree and has a name that does not
start with "xep-" (you may change this or ask the author to change it).
- Make sure the version is `0.0.1` and the status is `ProtoXEP` (you may fix
this or ask the author to fix it).
- You may want to build the protoxep locally and ensure the HTML and PDF look
okay.
- Merge the PR as described in "Merging a PR". Once the email has been sent,
continue here.
- Create a card for the protoxep on the [Council Trello] under "Proposed
Agendums".
- Attach the PR to the card and link the generated HTML.
- Comment on the PR with a link to the card, thanking the author for their
submission and letting them know that their XEP will be voted on within the
next two weeks.
- If the council forgets and doesn't vote on the protoxep, pester them until
they do.
- If the council rejects the XEP, you're done (leave the XEP in the inbox and
inform the author of the councils decision). Otherwise, see
"Promoting a ProtoXEP".
Promoting a ProtoXEP
--------------------
- It is easiest to start a new branch, in case you screw something up on the
way.
- Once the council approves a ProtoXEP, *copy* it out of the inbox and into the
root, assigning it the next available number in the XEP series.
- Modify the `<number/>` element in the XML file to match.
- Set the version to `0.1` and the initials to `XEP Editor: xyz` (replacing
"xyz" with your own initials).
- Remove the `<interim/>` element from the XML file if it is included.
- Set the status to `Experimental`.
- Add a reference to the XEP in `xep.ent`.
- Make a commit.
- Treat your branch as you would treat a [Ready to Merge] PR in "Merging a PR".
(you dont need to create another branch though.)
Promoting XEPs
--------------
Ensure that the following sections exist (if not, ask the author to add them
before promoting the XEP):
- Security Considerations
- IANA Considerations
- XMPP Registrar Considerations
- XML Schema (for protocol specifications)
You can also refer to `xep-template.xml` for a recommended list of sections and
whether or not they are required.
For a helpful graph of how XEP promotion works, see [XEP-0001].
Deferring XEPs
--------------
Before Deferring XEPs, read the "General notes on making changes" section.
XEPs get deferred after 12 months of inactivity. There is a tool which handles
that process automatically, if it is invoked regularly.
First of all, you need an up-to-date ``xeplist.xml``:
make build/xeplist.xml
To get a list of XEPs which need to be deferred (without changing anything),
run:
./tools/deferrals.py -v
To apply the deferrals, make a new feature branch and execute:
./tools/deferrals.py -m 'initials'
where you replace ``initials`` with your editor initials so that it is obvious
who made the change (those initials will be used in the revision block).
This will modify the XEPs in-place. It uses heuristics for incrementing the
version number, finding and inserting the revision block as well as changing
the status. Yes, it involves regular expressions (because we dont want to
fully re-write the XML to keep the diffs minimal). It is thus vital that you
**use `git diff` to ensure that the changes are sane**. If the changes
are sane, make a commit and merge to master as described in "Merging a PR",
in accordance with the "General notes on making changes".
Merging a PR
------------
Before Merging a PR, read the "General notes on making changes" section.
When you get to the point that the PR is [Ready to Merge], do the following:
1. Create a new branch off master called ``feature/xep-1234`` (if the PR
touches multiple XEPs, I call it ``feature/xep-0678,xep-0789``).
2. Merge all [Ready to Merge] PRs which affect the XEP(s) into that branch.
3. Resolve conflicts.
4. If the PRs introduced multiple revision blocks, squash it down to a single
revision block. Set "XEP Editor (initials)" as author of the revision block
and add the initials of the original PR authors to the changelog entries.
(If that doesnt make sense to you, youll find plenty examples in the
XEPs.)
5. Ensure that everything builds by performing a full docker build (see above).
(Once the docker build reaches the point where the XEPs are built, you can
switch branches and work on another PR.)
6. If the build passes, check that the generated files look sane by running the
docker container.
7. Merge the PR into master. If you are working on independent changes to
multiple XEPs, you can merge them all in one go.
8. If you merged multiple things into master, re-do the docker build check.
9. Push.
10. Go back to "General notes on making changes".
[XEP-0001]: https://xmpp.org/extensions/xep-0001.html
[XEP-0053]: https://xmpp.org/extensions/xep-0053.html
[Editor Trello]: https://trello.com/b/gwcOFnCr
[Council Trello]: https://trello.com/b/ww7zWMlI
[Needs Council]: https://github.com/xsf/xeps/labels/Needs%20Council
[Needs Board]: https://github.com/xsf/xeps/labels/Needs%20Board
[ProtoXEP]: https://github.com/xsf/xeps/labels/ProtoXEP
[Go wiki]: https://golang.org/wiki/Gardening
[`is:open is:pr no:assignee`]: https://github.com/xsf/xeps/pulls?utf8=%E2%9C%93&q=is%3Aopen%20is%3Apr%20no%3Aassignee%20
[Needs Author]: https://github.com/xsf/xeps/labels/Needs%20Author
[Ready to Merge]: https://github.com/xsf/xeps/labels/Ready%20to%20Merge
[Needs List Discussion]: https://github.com/xsf/xeps/labels/Needs%20List%20Discussion
[Editorial Change]: https://github.com/xsf/xeps/labels/Editorial%20Change
[xep-attic]: https://github.com/xsf/xep-attic
[Docker Build]: https://hub.docker.com/r/xmppxsf/xeps/builds/
[@horazont]: https://github.com/horazont/
[jonasw]: https://wiki.xmpp.org/web/User:Jwi
[modeline]: # ( vim: set fenc=utf-8 ff=unix spell spl=en textwidth=80: )

56
all.sh
View File

@ -1,56 +0,0 @@
#!/bin/sh
# for all XEPs, generates HTML files and IETF-style reference, then copies XML file
# usage: ./all.sh
## LICENSE ##
#
# Copyright (c) 1999 - 2013 XMPP Standards Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
## END LICENSE ##
xeppath=/var/www/vhosts/xmpp.org/extensions
ls xep-0*.xml > tmp1.txt
sed s/^xep-// tmp1.txt > tmp2.txt
sed s/.xml$// tmp2.txt > nums.txt
rm tmp*.txt
while read f
do
xsltproc xep.xsl xep-$f.xml > $xeppath/xep-$f.html
xsltproc ref.xsl xep-$f.xml > $xeppath/refs/reference.XSF.XEP-$f.xml
xsltproc examples.xsl xep-$f.xml > $xeppath/examples/$f.xml
./gen.py $f
cp xep-$f.xml $xeppath/
./gen.py $f
done < nums.txt
rm nums.txt
xsltproc xep.xsl xep-README.xml > $xeppath/README.html
xsltproc xep.xsl xep-template.xml > $xeppath/template.html
cp *.dtd $xeppath/
cp *.ent $xeppath/
cp *.shtml $xeppath/
cp *.xsd $xeppath/
# END

View File

@ -1,196 +0,0 @@
#!/usr/bin/env python
# File: announce.py
# Version: 0.9
# Description: a script for announcing XEPs
# Last Modified: 2016-10-03
# Author: Peter Saint-Andre (stpeter@jabber.org)
# License: public domain
# HowTo: ./announce.py xepnum
## LICENSE ##
#
# Copyright (c) 1999 - 2010 XMPP Standards Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
## END LICENSE ##
# IMPORTS:
#
import glob
import os
from select import select
import smtplib
import socket
from string import split,strip,join,find
import sys
import time
from xml.dom.minidom import parse,parseString,Document
def getText(nodelist):
thisText = ""
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
thisText = thisText + node.data
return thisText
# get the seconds in the Unix era
now = int(time.time())
# READ IN ARGS:
#
# 1. XEP number
xepnum = sys.argv[1];
xepfile = 'xep-' + xepnum + '.xml'
# PARSE XEP HEADERS:
#
# - title
# - abstract
# - version
# - date
# - initials
# - remark
thexep = parse(xepfile)
xepNode = (thexep.getElementsByTagName("xep")[0])
headerNode = (xepNode.getElementsByTagName("header")[0])
titleNode = (headerNode.getElementsByTagName("title")[0])
title = getText(titleNode.childNodes)
abstractNode = (headerNode.getElementsByTagName("abstract")[0])
abstract = getText(abstractNode.childNodes)
statusNode = (headerNode.getElementsByTagName("status")[0])
xepstatus = getText(statusNode.childNodes)
typeNode = (headerNode.getElementsByTagName("type")[0])
xeptype = getText(typeNode.childNodes)
revNodes = headerNode.getElementsByTagName("revision")
revNode = revNodes[0]
versionNode = (revNode.getElementsByTagName("version")[0])
version = getText(versionNode.childNodes)
dateNode = (revNode.getElementsByTagName("date")[0])
date = getText(dateNode.childNodes)
initialsNode = (revNode.getElementsByTagName("initials")[0])
initials = getText(initialsNode.childNodes)
remNode = (revNode.getElementsByTagName("remark")[0])
# could be <p> or <ul>
testRemarkNode = remNode.firstChild.nodeName
# print testRemarkNode
if (testRemarkNode == "p"):
remarkNode = (remNode.getElementsByTagName("p")[0])
remark = getText(remarkNode.childNodes)
else:
remark = "[See revision history]"
# what kind of action are we taking?
xepflag = ""
if (version == "0.1" or version == "0.1.0"):
xepflag = "new"
elif ((version == "1.0" or version == "1.0.0") and xeptype == "Standards Track"):
xepflag = "draft"
elif ((version == "1.0" or version == "1.0.0") and xeptype != "Standards Track"):
xepflag = "active"
elif (version == "2.0" or version == "2.0.0"):
xepflag = "final"
elif (xepstatus == "Retracted"):
xepflag = "retract"
elif (xepstatus == "Deprecated"):
xepflag = "deprecate"
elif (xepstatus == "Obsolete"):
xepflag = "obsolete"
elif (xepstatus == "Deferred"):
xepflag = "defer"
# generate the diffs URL
if len(revNodes) > 1:
prevRevNode = revNodes[1]
prevVersionNode = (prevRevNode.getElementsByTagName("version")[0])
prevVersion = getText(prevVersionNode.childNodes)
diffs = 'https://xmpp.org/extensions/diff/api/xep/' + xepnum + '/diff/' + prevVersion + '/vs/' + version
else:
diffs = 'N/A'
## SEND MAIL:
#
# From: editor@xmpp.org
# To: standards@xmpp.org
# Subject: UPDATED: XEP-$xepnum ($title)
# [or "NEW..." if version 0.1]
# Body:
# Version $version of XEP-$xepnum ($title) is now available.
# Abstract: $abstract
# Changelog: $remark ($initials)
# Diff: $diffs ### no longer in use
# URL: https://xmpp.org/extensions/xep-$xepnum.html
fromaddr = "editor@xmpp.org"
# for testing...
# toaddrs = "stpeter@jabber.org"
# for real...
toaddrs = "standards@xmpp.org"
if xepflag == "new":
thesubject = 'NEW: XEP-'
elif xepflag == "draft":
thesubject = 'DRAFT: XEP-'
elif xepflag == "final":
thesubject = 'FINAL: XEP-'
elif xepflag == "active":
thesubject = 'ACTIVE: XEP-'
elif xepflag == "retract":
thesubject = 'RETRACTED: XEP-'
elif xepflag == "deprecate":
thesubject = 'DEPRECATED: XEP-'
elif xepflag == "obsolete":
thesubject = 'OBSOLETE: XEP-'
elif xepflag == "defer":
thesubject = 'DEFERRED: XEP-'
else:
thesubject = 'UPDATED: XEP-'
thesubject = thesubject + xepnum + ' (' + title + ')'
versionline = 'Version ' + version + ' of XEP-' + xepnum + ' (' + title + ') has been released.'
abstractline = 'Abstract: ' + abstract
changelogline = 'Changelog: ' + remark + ' (' + initials + ')'
diffsline = 'Diff: ' + diffs
urlline = 'URL: https://xmpp.org/extensions/xep-' + xepnum + '.html'
msg = "From: XMPP Extensions Editor <%s>\r\n" % fromaddr
msg = msg + "To: %s\r\n" % toaddrs
msg = msg + "Subject: %s\r\n" % thesubject
msg = msg + versionline
msg = msg + "\r\n\n"
msg = msg + abstractline
msg = msg + "\r\n\n"
msg = msg + changelogline
msg = msg + "\r\n\n"
msg = msg + diffsline
msg = msg + "\r\n\n"
msg = msg + urlline
msg = msg + "\r\n\n"
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
# END

432
gen.py
View File

@ -1,432 +0,0 @@
#!/usr/bin/env python
# File: gen.py
# Version: 0.2
# Description: a renewed XEP compilation tool
# Last Modified: 2009
# Author: Tobias Markmann (tm@ayena.de)
# HowTo: ./gen.py xep-####.xml
## LICENSE ##
#
# Copyright (c) 1999 - 2010 XMPP Standards Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
## END LICENSE ##
import pickle
import commands
import os
import re
import sys
import getopt
import glob
import tempfile
from xepinfo import XEPInfo
from xeputil import getLatestXEPFilename
from xml.dom.minidom import parse,parseString,Document,getDOMImplementation
# for serializing inline images
import base64
import urlparse
import urllib
XEPPATH = "/var/www/vhosts/xmpp.org/extensions"
CONFIGPATH = "/var/local/xsf"
verbose = False
fast = False
last_build = {}
files_to_delete = [];
def serializeInlineImage(output_dir, xep_nr, no, attrValue):
up = urlparse.urlparse(attrValue)
if up.scheme == 'data':
head, data = up.path.split(',')
bits = head.split(';')
mime_type = bits[0] if bits[0] else 'text/plain'
charset, b64 = 'ASCII', False
for bit in bits[1]:
if bit.startswith('charset='):
charset = bit[8:]
elif bit == 'base64':
b64 = True
# Do something smart with charset and b64 instead of assuming
plaindata = base64.b64decode(data)
# Do something smart with mime_type
if mime_type in ('image/png', 'image/jpeg'):
file_ext = mime_type.split('/')[1]
f = open(output_dir + '/' + 'inlineimage-' + xep_nr + '-' + str(no) + '.' + file_ext, 'wb')
f.write(plaindata)
elif up.scheme == 'http':
file_name, file_ext = os.path.splitext(up.path)
urllib.urlretrieve(attrValue, output_dir + '/' + 'inlineimage-' + xep_nr + '-' + str(no) + file_ext)
def serializeXEPInlineImages(output_dir, xep_nr, filename):
dom = parse(filename)
imgs = dom.getElementsByTagName('img')
for (no, img) in enumerate(imgs):
serializeInlineImage(output_dir, xep_nr, no, img.attributes["src"].value)
def getText(nodelist):
thisText = ""
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
thisText = thisText + node.data
return thisText
def executeCommand( cmd ):
error, desc = commands.getstatusoutput( cmd )
return error, desc + "\n" + "executed cmd: " + cmd
## creates a HTML table (for the human reader) and XML table (for bots)
class XEPTable:
def __init__(self, filename, shortXMLfilename):
self.filename = filename
self.shortXMLfilename = shortXMLfilename
try:
self.tableFile = parse(filename)
except:
impl = getDOMImplementation()
self.tableFile = impl.createDocument(None, "table", None)
self.tableFile.getElementsByTagName("table")[0].setAttribute("class", "sortable")
self.tableFile.getElementsByTagName("table")[0].setAttribute("id", "xeplist")
self.tableFile.getElementsByTagName("table")[0].setAttribute("cellspacing", "0")
self.tableFile.getElementsByTagName("table")[0].setAttribute("cellpadding", "3")
self.tableFile.getElementsByTagName("table")[0].setAttribute("border", "1")
header = parseString(
'''<tr class='xepheader'>
<th align='left'>Number</th>
<th align='left'>Name</th>
<th align='left'>Type</th>
<th align='left'>Status</th>
<th align='left'>Date</th>
</tr>''')
self.tableFile.getElementsByTagName("table")[0].appendChild(header.getElementsByTagName("tr")[0])
try:
self.botsFile = parse(shortXMLfilename)
except:
impl = getDOMImplementation()
self.botsFile = impl.createDocument(None, "xeps", None)
def save(self):
f = open(self.filename, "wb")
self.tableFile.getElementsByTagName("table")[0].normalize()
f.write(self.tableFile.toxml())
f.close()
f = open(self.shortXMLfilename, "wb")
self.botsFile.getElementsByTagName("xeps")[0].normalize()
f.write(self.botsFile.toxml())
f.close()
def setXEP(self, info):
## set for HTML table
rows = self.tableFile.getElementsByTagName("tr")
xeprow = 0
for row in rows:
if row.getAttribute("id") == "xep" + info.getNr():
xeprow = row
break
if xeprow == 0:
xeprow = self.tableFile.createElement("tr")
self.tableFile.getElementsByTagName("table")[0].appendChild(xeprow)
self.tableFile.getElementsByTagName("table")[0].appendChild(self.tableFile.createTextNode('''
'''))
xeprow.setAttribute("id", "xep" + info.getNr())
xeprow.setAttribute("class", "tablebody XEP-" + info.getStatus())
else:
xeprow.setAttribute("class", "tablebody XEP-" + info.getStatus())
while(xeprow.hasChildNodes()):
xeprow.removeChild(xeprow.firstChild)
col = parseString('''<td valign='top'><a href='/extensions/xep-''' + info.getNr() + ".html'>XEP-" + info.getNr() + '''</a> <a href='/extensions/xep-''' + info.getNr() + '''.pdf'>(PDF)</a></td>''')
xeprow.appendChild(col.getElementsByTagName("td")[0])
col = parseString("<td valign='top'>" + info.getTitle() + "</td>")
xeprow.appendChild(col.getElementsByTagName("td")[0])
col = parseString("<td valign='top'>" + info.getType() + "</td>")
xeprow.appendChild(col.getElementsByTagName("td")[0])
col = parseString("<td valign='top'>" + info.getStatus() + "</td>")
xeprow.appendChild(col.getElementsByTagName("td")[0])
col = parseString("<td valign='top'>" + info.getDate() + "</td>")
xeprow.appendChild(col.getElementsByTagName("td")[0])
## set for bots file
xeps = self.botsFile.getElementsByTagName("xep")
xep = 0
for xeps_xep in xeps:
if xeps_xep.getElementsByTagName("number")[0].firstChild.data == info.getNr():
xep = xeps_xep
break
if xep == 0:
xep = self.botsFile.createElement("xep")
self.botsFile.getElementsByTagName("xeps")[0].appendChild(xep)
self.botsFile.getElementsByTagName("xeps")[0].appendChild(self.botsFile.createTextNode('''
'''))
else:
while(xep.hasChildNodes()):
xep.removeChild(xep.firstChild)
child = parseString("<number>" + info.getNr() + "</number>")
xep.appendChild(child.getElementsByTagName("number")[0])
child = parseString("<name>" + info.getTitle() + "</name>")
xep.appendChild(child.getElementsByTagName("name")[0])
child = parseString("<type>" + info.getType() + "</type>")
xep.appendChild(child.getElementsByTagName("type")[0])
child = parseString("<status>" + info.getStatus() + "</status>")
xep.appendChild(child.getElementsByTagName("status")[0])
child = parseString("<updated>" + info.getDate() + "</updated>")
xep.appendChild(child.getElementsByTagName("updated")[0])
child = parseString("<shortname>" + info.getShortname() + "</shortname>")
xep.appendChild(child.getElementsByTagName("shortname")[0])
child = parseString("<abstract>" + info.getAbstract() + "</abstract>")
xep.appendChild(child.getElementsByTagName("abstract")[0])
def filebase( filename ):
return os.path.splitext(os.path.basename(filename))[0]
def checkError( error, desc):
global verbose
if error != 0:
if verbose:
print "Error: ", desc
return False
return True
def fileHash( filename ):
f = open(filename, "rb")
import hashlib
h = hashlib.sha1()
h.update(f.read())
hash = h.hexdigest()
f.close()
return hash
def loadDict( filename ):
try:
f = open(filename, "rb")
di = pickle.load(f)
f.close()
return di
except:
print "failed loading dict."
return {}
def saveDict( filename, di ):
f = open(filename, "w")
pickle.dump(di, f)
f.close()
def buildXHTML( file, nr ):
error, desc = executeCommand("xsltproc xep.xsl " + file + " > " + XEPPATH + "/xep-" + nr + ".html")
if not checkError(error, desc):
return False
error, desc = executeCommand("xsltproc ref.xsl xep-" + nr + ".xml > " + XEPPATH + "/refs/reference.XSF.XEP-" + nr + ".xml")
if not checkError(error, desc):
return False
error, desc = executeCommand("xsltproc examples.xsl xep-" + nr + ".xml > " + XEPPATH + "/examples/" + nr + ".xml")
if not checkError(error, desc):
return False
error, desc = executeCommand(" cp xep-" + nr + ".xml " + XEPPATH + "/")
if not checkError(error, desc):
return False
return True
def buildPDF( file, nr ):
serializeXEPInlineImages("/tmp/xepbuilder", nr, file)
error, desc = executeCommand("xsltproc -o /tmp/xepbuilder/xep-" + nr + ".tex.xml xep2texml.xsl " + file)
if not checkError(error, desc):
return False
error, desc = executeCommand("texml -e utf8 /tmp/xepbuilder/xep-" + nr + ".tex.xml /tmp/xepbuilder/xep-" + nr + ".tex")
if not checkError(error, desc):
return False
#detect http urls and escape them to make them breakable
# this should match all urls in free text; not the urls in xml:ns or so..so no " or ' in front.
error, desc = executeCommand('''sed -i 's|\([\s"]\)\([^"]http://[^ "]*\)|\1\\path{\2}|g' /tmp/xepbuilder/xep-''' + nr + ".tex")
if not checkError(error, desc):
return False
#adjust references
error, desc = executeCommand('''sed -i 's|\\hyperref\[#\([^}]*\)\]|\\hyperref\[\1\]|g' /tmp/xepbuilder/xep-''' + nr + ".tex")
if error != 0:
if verbose == 1:
print "Error: ", desc
return False
error, desc = executeCommand('''sed -i 's|\\pageref{#\([^}]*\)}|\\pageref{\1}|g' /tmp/xepbuilder/xep-''' + nr + ".tex")
if not checkError(error, desc):
return False
olddir = os.getcwd()
os.chdir("/tmp/xepbuilder")
error, desc = executeCommand("xelatex -interaction=batchmode xep-" + nr + ".tex")
#if not checkError(error, desc):
# os.chdir(olddir)
# return False
#error, desc = executeCommand("xelatex -interaction=batchmode xep-" + nr + ".tex")
#if not checkError(error, desc):
# os.chdir(olddir)
# return False
os.chdir(olddir)
error, desc = executeCommand("cp /tmp/xepbuilder/xep-" + nr + ".pdf " + XEPPATH + "/")
if not checkError(error, desc):
return False
return True
def buildXEP( filename ):
nr = re.match("xep-(\d\d\d\d).xml", filename).group(1)
xepfilepath = getLatestXEPFilename("./", nr);
if not xepfilepath:
print "getLatestXEPContent (ERROR)"
return
files_to_delete.append(xepfilepath)
if not fast:
print "Building " + filename + ": ",
if buildXHTML( xepfilepath, nr ):
print "XHTML(OK) / ",
else:
print "XHTML(ERROR) / ",
if buildPDF( xepfilepath, nr ):
print "PDF(OK)"
else:
print "PDF(ERROR)"
else:
print "Building " + filename + " (FAST MODE)"
x = XEPTable(CONFIGPATH + "/extensions.xml", XEPPATH + "/xeps.xml")
xinfo = XEPInfo(xepfilepath, False)
x.setXEP( xinfo )
x.save()
def buildAll():
files = glob.glob('xep-????.xml')
files.sort(key=lambda x: x.lower())
for file in files:
buildXEP( file )
def makeBundle():
print "Creating the bundle...",
executeCommand("mkdir /tmp/xepbundle")
executeCommand("cp " + XEPPATH + "/*.pdf " + "/tmp/xepbundle")
executeCommand("tar -cf /tmp/xepbundle.tar -C /tmp xepbundle")
executeCommand("pbzip2 -f -9 /tmp/xepbundle.tar")
executeCommand("mv -f /tmp/xepbundle.tar.bz2 " + XEPPATH + "/xepbundle.tar.bz2")
executeCommand("rm -rfd /tmp/xepbundle")
print "DONE"
def usage():
print "gen.py: generate nice XHTML and beautiful PDF out of the XEP XML files"
print ""
print "Usage:"
print "gen.py xep-####.xml"
print ""
print "Options:"
print "-v Enable verbose output for debugging."
print "-a Build all available XEPs."
print "-f Fast; means no actual compiling is done."
def main(argv):
global verbose
global CONFIGPATH
global fast
buildall = False
try:
options, remainder = getopt.gnu_getopt(argv, "vaf")
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in options:
if opt in ('-v'):
verbose = True
elif opt in ('-a'):
buildall = True
elif opt in ('-f'):
fast = True
if len(remainder) > 0:
try:
xep = int(remainder[0])
xep = "xep-%04d.xml" % xep
except:
xep = remainder[0]
executeCommand("mkdir /tmp/xepbuilder")
executeCommand("cp ../images/xmpp.pdf /tmp/xepbuilder/xmpp.pdf")
executeCommand("cp ../images/xmpp-text.pdf /tmp/xepbuilder/xmpp-text.pdf")
executeCommand("cp -r deps/* /tmp/xepbuilder/")
executeCommand("cp xep.ent /tmp/xep.ent")
files_to_delete.append("/tmp/xep.ent")
if buildall:
buildAll()
else:
buildXEP( xep )
# remove xep temporary files
for filename in files_to_delete:
executeCommand("rm " + filename)
executeCommand("sed -e '1s/<?[^?]*?>//' " + CONFIGPATH + "/extensions.xml > " + XEPPATH + "/../includes/xeplist.txt")
executeCommand("rm -rfd /tmp/xepbuilder")
makeBundle()
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -23,7 +23,7 @@
<dependencies>
<spec>XMPP Core</spec>
</dependencies>
<supersedes>XEP-0077</supersedes>
<supersedes><spec>XEP-0077</spec></supersedes>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<author>
@ -72,11 +72,11 @@
<di>
<dt>Account Management</dt>
<dd>Gestion of a client XMPP account on a given server deployment. An account is being defined by the locale part of the JID, and by the authentication mechanisms available for this account.</dd>
<dt>In-Band</dt>
<dd>Capacity of acting directly through a XMPP stream. As a consequence, an In-Band Account Management MAY allow users to bootstrap the existence of their account, and oppositely to end it, or modify it, without ever having to use another medium (like the web for instance), or without the existence of a previous account.</dd>
<dt>Storage Mechanism</dt>
<dd>The internal logics of a server to store authentication data.</dd>
</di>
<di><dt>In-Band</dt>
<dd>Capacity of acting directly through a XMPP stream. As a consequence, an In-Band Account Management MAY allow users to bootstrap the existence of their account, and oppositely to end it, or modify it, without ever having to use another medium (like the web for instance), or without the existence of a previous account.</dd></di>
<di><dt>Storage Mechanism</dt>
<dd>The internal logics of a server to store authentication data.</dd></di>
</dl>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
@ -481,13 +481,13 @@
<li>For a better user experience, it is important to provide &lt;challenge/> fallbacks rather than directly fail with a &lt;failure/> on the first user error. <cite>XEP-0158</cite> for instance proposes to fail directly on a wrong answer to a CAPTCHA challenge, while it is well known that many actual human users regularly fails, sometimes even several, captchas before succeeding one. As a consequence, in such a case or other similar challenge, it is better to return a new challenge (a new CAPTCHA for instance) rather than cancelling the negotiation, doing so eventually only after a few retries.</li>
<li>The storage mechanism does not mean necessarily that credentials have to be stored in the given form, in particular when the server estimates a storage mechanism being stronger than the one desired by the user, and still without losing any authentication possibility. For instance if a client was to exchange credentials in PLAIN, and if the server usually provides SCRAM-SHA1, SCRAM-SHA-256 and PLAIN authentication mechanisms, then it would be wise to store it as both SCRAM-SHA-1 and SCRAM-SHA-256 instead of PLAIN. This way the security of the password is highly renforced in the case of the database being stolen and the three authentication mechanisms are still available to this user. Of course it would have been even more secure for the client itself to exchange the credentials as SCRAM-SHA-1 and SCRAM-SHA-256 from the start, because by exchanging PLAIN data, possibility is given to a man-in-the-middle attack to steal directly the password during this one-time account registration.</li>
<li>Security may have a price. If you were to store credentials with SCRAM-SHA-256 only, and later you change to a client which supports only PLAIN and SCRAM-SHA-1, you may fall in a case where you force yourself to log in using PLAIN. For this reason, a good client implementation SHOULD be able to determine such edge case. In the previous case, if possible, it SHOULD have stored both SCRAM-SHA-1 and SCRAM-SHA-256 on registration or silently modify later its storage.</li>
<li>When registering a new account, considering that the user has obviously not been authenticated yet, the server MUST NOT rely on the 'from' value of the initiating stream. In particular:</li>
<li>When registering a new account, considering that the user has obviously not been authenticated yet, the server MUST NOT rely on the 'from' value of the initiating stream. In particular:
<ul>
<li>the server MUST NOT decide whether or not to propose the &lt;registration/> feature based on the existence of the JID filled in 'from'. Doing so would leak away information about the existence of a JID which could therefore be sent undesirable messages. Being consistent on showing the feature forces to try to register which can already eliminates part of the risk if the challenge provides some bot protection (for instance CAPTCHAs).
<br />A perfectly valid alternative would be to always provide the &lt;registration/> feature when no "from" is filled but never provide it when a "from is filled" (no matter it is an existing JID or not). This consistent logics does not leak information.</li>
<li>Do not modify the SASL authentication's mechanisms listed in the &lt;mechanisms/> feature depending on the 'from'. Even though a given JID might not be able to connect with some mechanisms because the credentials storage is incompatible, this would leak information on the kind of storage mechanism used for this user. This information would allow attackers to determine, then target, users whose storage would be weaker.
<br/>Of course this particular point might cause issues for users regularly changing their clients or log in from various computer. For instance the SCRAM-SHA-1 and SCRAM-SHA-256 storage are incompatible. If you first registered by specifying the SCRAM-SHA-256 storage, then on another client which does not support SCRAM-SHA-256 or even who supports it, but for some reason always try and gives priority to SCRAM-SHA-1, the user could be found in a situation where he never manages to authenticate while providing the right password. For this reason, it could be wiser for server deployments to choose compatible mechanisms, when possible. On client side, if they are provided a raw password, instead of pre-computed data for a specific mechanism, then they should intelligently try the various mechanisms, starting from the one they consider the stronger. Hence try SCRAM-SHA-256, then SCRAM-SHA-1 if the first failed, then only if both failed, tell the user that authentication failed (note that the client should not try PLAIN as a last fallback, because we remind that any SCRAM-* storage is compatible with the SASL PLAIN mechanism. Trying PLAIN would therefore be a security risk.</li>
</ul>
<li><p>the server MUST NOT decide whether or not to propose the &lt;registration/> feature based on the existence of the JID filled in 'from'. Doing so would leak away information about the existence of a JID which could therefore be sent undesirable messages. Being consistent on showing the feature forces to try to register which can already eliminates part of the risk if the challenge provides some bot protection (for instance CAPTCHAs).</p>
<p>A perfectly valid alternative would be to always provide the &lt;registration/> feature when no "from" is filled but never provide it when a "from is filled" (no matter it is an existing JID or not). This consistent logics does not leak information.</p></li>
<li><p>Do not modify the SASL authentication's mechanisms listed in the &lt;mechanisms/> feature depending on the 'from'. Even though a given JID might not be able to connect with some mechanisms because the credentials storage is incompatible, this would leak information on the kind of storage mechanism used for this user. This information would allow attackers to determine, then target, users whose storage would be weaker.</p>
<p>Of course this particular point might cause issues for users regularly changing their clients or log in from various computer. For instance the SCRAM-SHA-1 and SCRAM-SHA-256 storage are incompatible. If you first registered by specifying the SCRAM-SHA-256 storage, then on another client which does not support SCRAM-SHA-256 or even who supports it, but for some reason always try and gives priority to SCRAM-SHA-1, the user could be found in a situation where he never manages to authenticate while providing the right password. For this reason, it could be wiser for server deployments to choose compatible mechanisms, when possible. On client side, if they are provided a raw password, instead of pre-computed data for a specific mechanism, then they should intelligently try the various mechanisms, starting from the one they consider the stronger. Hence try SCRAM-SHA-256, then SCRAM-SHA-1 if the first failed, then only if both failed, tell the user that authentication failed (note that the client should not try PLAIN as a last fallback, because we remind that any SCRAM-* storage is compatible with the SASL PLAIN mechanism. Trying PLAIN would therefore be a security risk.</p></li>
</ul></li>
</ul>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>

View File

@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>

View File

@ -8,14 +8,44 @@
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header xml:base="sections/header.xml">
<header>
<title>Buddycloud Channels</title>
<abstract>This document describes a profile and conventions for usage of the PubSub protocol in the context of a new type of communication.</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-0059</spec>
<spec>XEP-0060</spec>
<spec>XEP-0313</spec>
<spec>XEP-0255</spec>
<spec>XEP-0107</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<author>
<firstname>Simon</firstname>
<surname>Tennant</surname>
<email>simon@buddycloud.com</email>
<jid>simon@buddycloud.com</jid>
</author>
<author>
<firstname>Lloyd</firstname>
<surname>Watkin</surname>
<email>lloyd@evilprofessor.co.uk</email>
<jid>lloyd@evilprofessor.co.uk</jid>
</author>
<author>
<firstname>Ashley</firstname>
<surname>Ward</surname>
<email>ashley.ward@surevine.com</email>
<jid>ashley.ward@surevine.com</jid>
</author>
<revision>
<version>0.0.2</version>
<date>2014-04-29</date>
@ -24,92 +54,8 @@
<p>First draft.</p>
</remark>
</revision>
<shortname>NOT_YET_ASSIGNED</shortname>
<legal>
<copyright>This XMPP Extension Protocol is copyright (c) 1999 - 2014
by the XMPP Standards Foundation (XSF).
</copyright>
<permissions> Permission is hereby granted, free of charge, to any
person obtaining a copy of this specification (the
"Specification"), to make use of the Specification without
restriction, including without limitation the rights to implement
the Specification in a software program, deploy the Specification in
a network service, and copy, modify, merge, publish, translate,
distribute, sublicense, or sell copies of the Specification, and to
permit persons to whom the Specification is furnished to do so,
subject to the condition that the foregoing copyright notice and
this permission notice shall be included in all copies or
substantial portions of the Specification. Unless separate
permission is granted, modified works that are redistributed shall
not contain misleading information regarding the authors, title,
number, or publisher of the Specification, and shall not claim
endorsement of the modified works by the authors, any organization
or project to which the authors belong, or the XMPP Standards
Foundation.
</permissions>
<warranty> ## NOTE WELL: This Specification is provided on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, express or implied, including, without limitation, any
warranties or conditions of TITLE, NON-INFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. In no event
shall the XMPP Standards Foundation or the authors of this
Specification be liable for any claim, damages, or other liability,
whether in an action of contract, tort, or otherwise, arising from,
out of, or in connection with the Specification or the
implementation, deployment, or other use of the Specification. ##
</warranty>
<liability> In no event and under no legal theory, whether in tort
(including negligence), contract, or otherwise, unless required by
applicable law (such as deliberate and grossly negligent acts) or
agreed to in writing, shall the XMPP Standards Foundation or any
author of this Specification be liable for damages, including any
direct, indirect, special, incidental, or consequential damages of
any character arising out of the use or inability to use the
Specification (including but not limited to damages for loss of
goodwill, work stoppage, computer failure or malfunction, or any and
all other commercial damages or losses), even if the XMPP Standards
Foundation or such author has been advised of the possibility of
such damages.
</liability>
<conformance>
This XMPP Extension Protocol has been contributed in full
conformance with the XSF's Intellectual Property Rights Policy (a
copy of which may be found at &lt;
<link url="http://xmpp.org/extensions/ipr-policy.shtml">http://xmpp.org/extensions/ipr-policy.shtml</link>
&gt; or obtained by writing to XSF, P.O. Box 1641, Denver, CO 80201
USA).
</conformance>
</legal>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0059</spec>
<spec>XEP-0060</spec>
<spec>XEP-0313</spec>
<spec>XEP-0255</spec>
<spec>XEP-0107</spec>
</dependencies>
<supersedes/>
<supersededby/>
<author xml:base="authors/simon-tennant.xml">
<firstname>Simon</firstname>
<surname>Tennant</surname>
<email>simon@buddycloud.com</email>
<jid>simon@buddycloud.com</jid>
</author>
<author xml:base="authors/lloyd-watkin.xml">
<firstname>Lloyd</firstname>
<surname>Watkin</surname>
<email>lloyd@evilprofessor.co.uk</email>
<jid>lloyd@evilprofessor.co.uk</jid>
</author>
<author xml:base="authors/ashley-ward.xml">
<firstname>Ashley</firstname>
<surname>Ward</surname>
<email>ashley.ward@surevine.com</email>
<jid>ashley.ward@surevine.com</jid>
</author>
</header>
<section1 topic="Buddycloud Introduction" anchor="Buddycloud Introduction" xml:base="sections/10.intro.xml">
<section1 topic="Buddycloud Introduction" anchor="Buddycloud Introduction">
<section2 topic="About Buddycloud" anchor="about-buddycloud">
<p>The Buddycloud project is a set of independently deployable services, that
inter-operate to create a rich collaboration service.
@ -188,7 +134,7 @@
</dl>
</section2>
</section1>
<section1 topic="Service Discovery" anchor="Finding-the-right-Buddycloud-server" xml:base="sections/30.discovery.xml">
<section1 topic="Service Discovery" anchor="Finding-the-right-Buddycloud-server">
<p>Each XMPP domain can have one Buddycloud server that serves user's channels.
Buddycloud clients and servers need to be able to discover the authoratative
Buddycloud server. find the
@ -196,7 +142,7 @@
<section2 topic="Discovery order" anchor="DISCOthenDNS">
<p>
To find the correct remote Buddycloud service for a domain, the Buddycloud
server should:
server should:</p>
<ol>
<li>Use a disco#items query against the XMPP service for the remote
Buddycloud domain.
@ -206,7 +152,6 @@
discovery method.
</li>
</ol>
</p>
</section2>
<section2 topic="Discovery using Disco" anchor="disco-discovery">
<p>The Buddycloud service first sends an items discovery request to the domain
@ -274,12 +219,12 @@
<p>
This example delegates all the Buddycloud service to an XMPP component
running the Buddycloud named
<i>buddycloud-component.verona.lit</i>
<em>buddycloud-component.verona.lit</em>
.
</p>
</section2>
</section1>
<section1 topic="Register" anchor="register" xml:base="sections/40.register.xml">
<section1 topic="Register" anchor="register">
<p>Upon connection to the buddycloud server a user should send a register
stanza.</p>
@ -300,15 +245,16 @@
</p>
</section1>
<section1 topic="Channel and Node Configuration" anchor="channel-config" xml:base="sections/50.node-config.xml">
<section1 topic="Channel and Node Configuration" anchor="channel-config">
<p>Node metadata is used to describe the channel to users. All nodes in a
channel have the same metadata and permission.
</p>
<section2 topic="Get Node Configuration" anchor="get-node-config"> - using disco-info
with the node specified - using <cite>XEP-0060</cite> 5.4 Discover Node Metadata
<section2 topic="Get Node Configuration" anchor="get-node-config">
<p>- using disco-info
with the node specified - using &xep0060; 5.4 Discover Node Metadata</p>
</section2>
<section2 topic="Set Node Configuration" anchor="set-node-config"> set Not sure what
goes here?
<section2 topic="Set Node Configuration" anchor="set-node-config"><p> set Not sure what
goes here?</p>
</section2>
<section2 topic="Default roles" anchor="default-roles">
<p> minimum setting/optional recommended fallbacks
@ -401,7 +347,6 @@
<p>Channel owners and moderators can also set the default affiliation for the
channel
</p>
<p>
<table caption="Channel Types">
<tr>
<th>Channel Type</th>
@ -429,8 +374,6 @@
</td>
</tr>
</table>
</p>
<p>
<table caption="Channel Access Models">
<tr>
<th>Access Model</th>
@ -455,7 +398,6 @@
</td>
</tr>
</table>
</p>
</section2>
<section2 topic="Well known nodes" anchor="well-known-nodes">
<p>Buddycloud is designed to be extended with new node and content types. To
@ -523,16 +465,14 @@
</table>
</section2>
</section1>
<section1 topic="Business Logic" anchor="biz-logic" xml:base="sections/55.application-logic.xml">
<section1 topic="Business Logic" anchor="biz-logic">
<section2 topic="PubSub for Humans" anchor="PubSub-for-humans">
<p> Buddycloud adapts <cite>XEP-0060</cite>'s machine-to-machine design goals with logic
and presets that work better in a social person-to-person and person-to-group
environment. For example, to discourage "glorifying the wicked", the list of
banned users is only presented to the channel's moderators.
</p>
<p>
<table caption="channel read permissions">
<thead>
<tr>
<th>Property</th>
<th>Access model</th>
@ -544,8 +484,6 @@
<th>Anonymous (e.g. web)</th>
<th>Banned users</th>
</tr>
</thead>
<tbody>
<tr>
<td>channel name</td>
<td>all</td>
@ -665,12 +603,8 @@
<td>no</td>
<td>no</td>
</tr>
</tbody>
</table>
</p>
<p>
<table caption="channel write permissions">
<thead>
<tr>
<th>Property</th>
<th>Producer</th>
@ -680,8 +614,6 @@
<th>Anonymous (e.g. web)</th>
<th>Banned users</th>
</tr>
</thead>
<tbody>
<tr>
<td>change channel name</td>
<td>only at creation time</td>
@ -745,9 +677,7 @@
<td>no</td>
<td>no</td>
</tr>
</tbody>
</table>
</p>
</section2>
<section2 topic="Maintain Similar Affiliations across Channel Nodes" anchor="rules-nodeaffiliations">
<p>A Buddycloud server MUST maintain similar affiliations and permissions for a subscribed
@ -762,7 +692,7 @@
</p>
</section2>
</section1>
<section1 topic="Pubsub Items" anchor="items" xml:base="sections/60.items.xml">
<section1 topic="Pubsub Items" anchor="items">
<p>Many of the item use cases follow those from <cite>XEP-0060</cite>. This section notes
the departures from the parent XEP and specific requirements.
@ -864,8 +794,8 @@
<iq from="buddycloud.capulet.lit" to="juliet@capulet.lit/bc-app" type="result" id="retractitem:32"/>
]]>
</example>
A retraction message is sent to all online clients, with an Atom tombstone to
replace the deleted post
<p>A retraction message is sent to all online clients, with an Atom tombstone to
replace the deleted post</p>
<example caption="The Buddycloud server sends retractions out to online clients">
<![CDATA[
<message from="buddycloud.capulet.lit" id="bc:MGV3B" to="benvolio@montague.lit">
@ -900,7 +830,7 @@
<strong>review</strong>
; extensions.
</p>
<section3 topic="Publishing" anchor="item-publishing"/>
<section3 topic="Publishing" anchor="item-publishing">
<p>The minimal payload for a publish request must be formatted as follows:
</p>
<example caption="The Entity publishes to a node">
@ -962,11 +892,11 @@
</li>
</ul>
</section4>
<section3 topic="Threading" anchor="item-threading"/>
</section3>
<section3 topic="Threading" anchor="item-threading">
<p>
Posts in Buddycloud can be formed into threads consisting of a parent post
and comments to a maximum thread depth of 1. Posts follow the
<a href="http://tools.ietf.org/html/rfc4685">ATOM threading specification</a>
and comments to a maximum thread depth of 1. Posts follow the &rfc4685;
and utilise the &amp;
<strong>thread</strong>
; namespace with the 'ref' attribute referring to the full global ID of the
@ -992,7 +922,7 @@
</entry>
]]>
</example>
<section4 topic="Error Cases" anchor="item-threading-errorcases"/>
<section4 topic="Error Cases" anchor="item-threading-errorcases">
<ul>
<li>
<em>parent-item-not-found</em>
@ -1003,7 +933,9 @@
: An attempt to comment on a comment will result in this error response
</li>
</ul>
<section3 topic="Referencing" anchor="item-referencing"/>
</section4>
</section3>
<section3 topic="Referencing" anchor="item-referencing">
<p>Within a single thread comments can reference other comments or the parent
item. This is for the purpose of making a comment to a post further back in
the thread.
@ -1052,6 +984,7 @@
</li>
</ul>
</section4>
</section3>
<section3 topic="Rating" anchor="item-rating">
<p>By
making use of the &amp;
@ -1119,13 +1052,13 @@
</section3>
</section2>
</section1>
<section1 topic="Channel subscriptions" anchor="subscriptions" xml:base="sections/70.subscriptions.xml">
<section1 topic="Channel subscriptions" anchor="subscriptions">
<p>Buddycloud clients follow <cite>XEP-0060</cite> subscription mechanisms for following and unfollowing a channel.</p>
</section1>
<section1 topic="Channel affiliations" anchor="affiliations" xml:base="sections/80.affiliations.xml">
<section1 topic="Channel affiliations" anchor="affiliations">
<section2 topic="Buddycloud to XEP-0060 mappings" anchor="affiliation-to-xep-0060-mappings">
<p>
Buddycloud channels build on XEP-0060's node affiliations.
Buddycloud channels build on XEP-0060's node affiliations.</p>
<table caption="Channel Affiliations">
<tr>
<th>XEP-0060 Affiliation</th>
@ -1183,10 +1116,9 @@
<td>RECOMMENDED</td>
</tr>
</table>
</p>
</section2>
</section1>
<section1 topic="Federation" anchor="federation" xml:base="sections/90.federation.xml">
<section1 topic="Federation" anchor="federation">
<section2 topic="Inbox" anchor="inbox">
</section2>
<section2 topic="Interaction With Other Services" anchor="Interaction-With-Other-Services">
@ -1204,7 +1136,7 @@
</p>
</section2>
</section1>
<section1 topic="Security Considerations" anchor="security-considerations" xml:base="sections/95.security.xml">
<section1 topic="Security Considerations" anchor="security-considerations">
<section2 topic="Server Trust" anchor="server-trust">
<p>
The Buddycloud server should make sure that the remote server

169
inbox/cap.xml Normal file
View File

@ -0,0 +1,169 @@
<?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>Atomically Compare-And-Publish PubSub Items</title>
<abstract>This specification provides a mechanism to atomically Compare-And-Publish items to a PubSub node.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XEP-0030</spec>
<spec>XEP-0060</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>cap</shortname>
&flow;
<revision>
<version>0.0.1</version>
<date>2017-04-20</date>
<initials>fs</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>This specification provides a mechanism to atomically publish
items to a PubSub node depending on the item ID of the node's latest
item. This allows to prevent race conditions and avoids data
loss in certain situations.</p>
</section1>
<section1 topic='Discoverying Support' anchor='disco'>
<p>If an entity supports the Compared-And-Publish feature it MUST
advertise the fact by returning a &lt;feature/&gt; with the 'var'
attribute set to 'urn:xmpp:pubsub:cap:0' in response to a &xep0030;
query for information.</p>
</section1>
<section1 topic='Compare-And-Publish PubSub Items' anchor='cap'>
<p>In order to atomically compare-and-publish an item, a client
sends an &IQ; with a 'pubsub' element qualified by the
'urn:xmpp:pubsub:cap:0' namespace. The element MUST contain the same
attributes and elements as the &lt;publish/&gt; element defined in
&xep0060; <em>and</em> it MUST contain a previd attribute containing
an item ID.</p>
<p>The PubSub service MUST only publish the item if the node's
latest item ID is equal to the ID found in the 'previd'
attribute.</p>
<example caption='Publisher publishes an item using Compare-And-Publish'><![CDATA[
<iq type='set'
from='hamlet@denmark.lit/blogbot'
to='pubsub.shakespeare.lit'
id='compare-and-publish1'>
<pubsub xmlns='urn:xmpp:pubsub:cap:0'>
<compare-and-publish
node='princely_musings'
previd='1'>
<item>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</publish>
</pubsub>
</iq>
]]></example>
<section2 topic='Successfully published an item using Compare-And-Publish'>
<p>If the 'previd' matched the latest item's ID and if the service
was able to successfully process the request then the protocol
continues as defined in <cite>XEP-0060 7.1.2</cite>.</p>
</section2>
<section2 topic='Could not publish because newest item ID did not match'>
<p>In case the Compare-And-Publish operation failed because the
latest node id is not the same as given in the 'previd' attribute
in the request, the server returns an &IQ; result with 'pubsub'
element qualified by the 'urn:xmpp:pubsub:cap:0' namespace which
contains a &lt;compare-and-publish-failed/&gt; element. The
element MUST have a 'id' attribute with the ID of the lastest
item.</p>
<example caption='Service returns IQ response notifying of failed Compare-And-Publish operation'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/blogbot'
id='compare-and-ublish1'>
<pubsub xmlns='urn:xmpp:pubsub:cap:0'>
<compare-and-publish-failed id='2'/>
</pubsub>
</iq>
]]></example>
</section2>
<section2 topic='Error cases'>
<p>All other error cases are handled as specified in
<cite>XEP-0060 § 7.1.3</cite></p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>This extension protocol does not add any further security
considerations to the ones mentioned in <cite>XEP-0060 §
14.</cite>.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with the Internet Assigned
Numbers Authority (IANA).</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>This specification defines the following XML namespaces:</p>
<ul>
<li>urn:xmpp:pubsub:cap:0</li>
</ul>
<code caption='Registry Submission'><![CDATA[
<var>
<name>urn:xmpp:pubsub:cap:0</name>
<desc>Indicates support for Compare-And-Publish</desc>
<doc>XEP-XXXX</doc>
</var>]]></code>
</section1>
<section1 topic='XML Schema' anchor='schema'>
<p>TODO: Add after the XEP leaves the 'experimental' state.</p>
</section1>
</xep>

View File

@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY rfc3921bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3921bis'>rfc3921bis</link></span> <note>RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3921bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3921bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>

View File

@ -117,7 +117,7 @@ Examples for balancing algorithms include:
<section1 topic='Protocol' anchor='protocol'>
<section2 topic='Discovering Support'>
An entity advertises support for this protocol by including the 'urn:xmpp:cmr:0' feature in its service discovery information features as specified in Service Discovery (XEP-0030) or section 6.3 of Entity Capabilities (XEP-0015).
<p>An entity advertises support for this protocol by including the 'urn:xmpp:cmr:0' feature in its service discovery information features as specified in Service Discovery (XEP-0030) or section 6.3 of Entity Capabilities (XEP-0015).</p>
<example caption='Service discovery information request'><![CDATA[
<iq xmlns='jabber:client'
@ -217,7 +217,7 @@ If the server is unable to change the message routing algorithm, then an error &
<section2 topic='Message Routing Hints'>
If allowed and supported by the server, clients are able to annotate message stanza with a routing hint, that SHOULD affect the used message routing algorithm for the annotated stanza.
<p>If allowed and supported by the server, clients are able to annotate message stanza with a routing hint, that SHOULD affect the used message routing algorithm for the annotated stanza.</p>
<section3 topic='Determing support'>
@ -306,7 +306,7 @@ The CMR state, ie. the used routing algorithm, is identical for every session of
<p>
<strong>Algorithm Namespace:</strong> 'urn:xmpp:cmr:all'
</p>
Deliver to all non-negative resources with share the same maximum priority. And if message type is 'chat', only to those that have opted in to receive chat messages.
<p>Deliver to all non-negative resources with share the same maximum priority. And if message type is 'chat', only to those that have opted in to receive chat messages.</p>
</section3>
@ -314,7 +314,7 @@ Deliver to all non-negative resources with share the same maximum priority. And
<p>
<strong>Algorithm Namespace:</strong> 'urn:xmpp:cmr:mostactive'
</p>
Deliver the message to the "most available" resource or resources, depending on the server's implementation.
<p>Deliver the message to the "most available" resource or resources, depending on the server's implementation.</p>
</section3>
@ -322,7 +322,7 @@ Deliver the message to the "most available" resource or resources, depending on
<p>
<strong>Algorithm Namespace:</strong> 'urn:xmpp:cmr:roundrobin'
</p>
Deliver the message to the next resource selected by a round-robin algorithm.
<p>Deliver the message to the next resource selected by a round-robin algorithm.</p>
</section3>
@ -330,7 +330,7 @@ Deliver the message to the next resource selected by a round-robin algorithm.
<p>
<strong>Algorithm Namespace:</strong> 'urn:xmpp:cmr:weighted'
</p>
Deliver the message to a resource selected by a weighted round-robin algorithm. The weight of a resource is determined by its priority.
<p>Deliver the message to a resource selected by a weighted round-robin algorithm. The weight of a resource is determined by its priority.</p>
</section3>
</section2>

282
inbox/colors.xml Normal file
View File

@ -0,0 +1,282 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY rgblind "<em>Red/Green-Blindness</em>">
<!ENTITY bblind "<em>Blue-Blindness</em>">
<!ENTITY cvd "Color Vision Deficiency">
<!ENTITY cvds "Color Vision Deficiencies">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Consistent Color Generation</title>
<abstract>This specification provides a set of algorithms to consistently generate colors given a string. The string can be a nickname, a JID or any other piece of information. All entities adhering to this specification generate the same color for the same string, which provides a consistent user experience across platforms.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies></dependencies>
<supersedes/>
<supersededby/>
<shortname>colors</shortname>
<author>
<firstname>Jonas</firstname>
<surname>Wielicki</surname>
<email>jonas@wielicki.name</email>
<jid>jonas@wielicki.name</jid>
</author>
<revision>
<version>0.0.1</version>
<date>2017-09-14</date>
<initials>jwi</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>Colors provide a valuable visual cue to recognize text. Recognition of colors works much faster than recognition of text. Together with the length and overall shape of a piece of text (such as a nickname), a color provides a decent amount of entropy to distinguish a reasonable amount of entities.</p>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>The color generation mechanism should provide the following features:</p>
<ul>
<li>Consistent generation of color across all platforms depending solely on the identifier used as input for the algorithm.</li>
<li>The system should be reasonably fast; it must be possible to, for example, apply it to all roster entries even of very large rosters in reasonable amount of time.</li>
<li>It must be able to provide decent contrast on any background.</li>
<li>The implementation should be stateless and not be complex.</li>
<li>A fallback path for users with common types of &cvds; must be provided.</li>
<li>A fallback path for systems which can only use colors from a restricted palette must be provided.</li>
</ul>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic='Generating a color' anchor='usecase-textcolor'>
<p>To generate a color from a string of text, the follownig algorithms are applied in order:</p>
<ol>
<li><link url='#algorithm-angle'>Generate an angle in the CbCr plane from the text</link>.</li>
<li>If enabled, <link url='#algorithm-cvd'>apply configured corrections for &cvds;</link>.</li>
<li><link url='#algorithm-cbcr'>Convert the angle to a CbCr pair</link>.</li>
<li>If the output device only supports a small palette of colors, <link url='#algorithm-mappalette'>map the CbCr value to the closest palette color</link>.</li>
<li>If the output device supports RGB output, <link url='#algorithm-rgb'>convert the CbCr pair to an RGB triple</link>.</li>
</ol>
</section2>
<section2 topic='Adding colors to participants of a conversation' anchor='usecase-nickcolor'>
<p>Implementations may colorize the participants of a conversation with an individual color to make them easier to distinguish.</p>
<p>In such cases, the color SHOULD be generated as described in the <link url='#usecase-textcolor'>Generating a color</link> section. The input used SHOULD be, in descending order of preference, (a) the name assigned in the roster, (b) the nickname from the conversation, (c) the bare JID.</p>
</section2>
<section2 topic='Auto-Generating Avatars' anchor='usecase-avatar'>
<p>Implementations may want to show a picture in connection with a contact even if the contact does not have an avatar defined (e.g. via &xep0084;).</p>
<p>In such cases, auto-generating an avatar SHOULD happen as follows:</p>
<ol>
<li>Obtain a name for the contact, in descending order of preference, (a) from the roster, (b) by using the nickname from the conversation, (c) by using the bare JID.</li>
<li>Generate a color as described in the <link url='#usecase-textcolor'>Generating a color</link> section.</li>
<li>Fill an implementation-defined background shape with that color.</li>
<li>Render the first character of the name in white or black centered on the square.</li>
</ol>
</section2>
</section1>
<section1 topic='Business Rules' anchor='rules'>
<ul>
<li>Implementations MUST allow the user to turn off any colorization completely.</li>
<li>Implementations MUST implement the &cvd; profiles and MUST allow the user to choose any of these profiles or to disable the correction.</li>
<li>Implementations MUST NOT share the &cvd; correction settings with other entities.</li>
</ul>
</section1>
<section1 topic='Algorithms' anchor='algorithm'>
<section2 topic='Angle generation' anchor='algorithm-angle'>
<p>Input: An identifier, encoded as octets of UTF-8 (&rfc3269;).</p>
<p>Output: Angle in the CbCr plane.</p>
<p>Note: The goal of this algorithm is to convert arbitrary text into a scalar value which can then be used to calculate a color. As it happens, the CbCr plane of the YCbCr space determines the color (while Y merely defines the lightness); thus, an angle in the CbCr plane serves as a good scalar value to select a color.</p>
<ol>
<li>Run the input through CRC32 as defined by zlib (TODO: add citation).</li>
<li>Take the lower 16 bits and XOR them with the upper 16 bits.</li>
<li>Divide the value by 65535 (use float division) and multiply it by 2&#960; (two Pi).</li>
</ol>
</section2>
<section2 topic='Corrections for &cvds;' anchor='algorithm-cvd'>
<p>Input: Angle in the CbCr plane.</p>
<p>Output: Angle in the CbCr plane.</p>
<p>Note: This algorithm will re-map the angle to map it away from ranges which can not be distinguished by people with the respective &cvds;.</p>
<section3 topic='Red/Green-blindness' anchor='algorithm-cvd-rg'>
<p>Divide the angle by two.</p>
</section3>
<section3 topic='Blue-blindness' anchor='algorithm-cvd-b'>
<p>Divide the angle by two and add &#960;/2 (half Pi).</p>
</section3>
</section2>
<section2 topic='CbCr generation' anchor='algorithm-cbcr'>
<p>Input: Angle in the CbCr plane, from the previous algorithm.</p>
<p>Output: Values for Cb and Cr in the YCbCr BT.601 color space in the range from -0.5 to 0.5.</p>
<p>Form a vector from the angle and project it to edges of a quad in 2D space with edge length 1 around (0, 0). The resulting coordinates are Cb and Cr:</p>
<code><![CDATA[float cr = sin(angle);
float cb = cos(angle);
float factor;
if (abs(cr) > abs(cb)) {
factor = 0.5 / abs(cr);
} else {
factor = 0.5 / abs(cb);
}
cb = cb * factor;
cr = cr * factor;
]]></code>
</section2>
<section2 topic='CbCr to RGB' anchor='algorithm-rgb'>
<p>Input: Values for Cb and Cr in the YCbCr BT.601 color space in the range from -0.5 to 0.5; Value for Y.</p>
<p>Output: Values for Red (R), Green (G) and Blue (B) in the RGB color space in the range from 0 to 1.</p>
<p>Note: The recommended value for Y is 0.732. See <link url='#impl-gamma'>Gamma Correction</link> for a discussion on the choice of Y.</p>
<ol>
<li>Calculate r, g and b according to BT.601:<code><![CDATA[float r = 2*(1 - KR)*cr + y;
float b = 2*(1 - KB)*cb + y;
float g = (y - KR*r - KB*b)/KG;
]]></code></li>
<li>Clip the values of r, g and b to the range from 0 to 1.</li>
</ol>
</section2>
<section2 topic='Adapting the Color for specific Background Colors' anchor='algorithm-bg'>
<p>Input: RGB values for the color to adapt (Ri, Gi, Bi) and for the background color to adapt to (Rb, Gb, Bb), in the range from 0 to 1 each.</p>
<p>Output: Values for Red (Rc), Green (Gc) and Blue (Bc) in the RGB color space in the range from 0 to 1.</p>
<ol>
<li>Invert the background color by subtracting the individual channels from 1 each:
<code><![CDATA[
rb = 1-rb;
gb = 1-gb;
bb = 1-bb;]]></code></li>
<li>Mix the inverted background with the color to adapt, using a mixing factor of 0.2:
<code><![CDATA[
rc = 0.2*rb + 0.8*ri;
gc = 0.2*gb + 0.8*gi;
bc = 0.2*bb + 0.8*bi;]]></code></li>
</ol>
</section2>
<section2 topic='RGB to YCbCr' anchor='algorithm-rgb2cbcr'>
<p>Input: Values for Red (R), Green (G) and Blue (B) in the RGB color space in the range from 0 to 1.</p>
<p>Output: Values for Cb and Cr in the YCbCr BT.601 color space in the range from -0.5 to 0.5; Value for Y.</p>
<p>Calculate Y, Cb and Cr according to BT.601:</p>
<code><![CDATA[
y = KR*r + (1 - KR - KB)*g + KB*b;
cb = (b - y) / (1 - KB) / 2
cr = (r - y) / (1 - KR) / 2
]]></code>
</section2>
<section2 topic='Conversion of an RGB color palette to a CbCr color palette' anchor='algorithm-genpalette'>
<p>Input: A set of RGB colors (each component from 0 to 1).</p>
<p>Output: A mapping from CbCr pairs (each component from -0.5 to 0.5) to RGB colors.</p>
<p>Note: when the algorithm finishes, the mapping maps CbCr values (rounded to two decimal places) to the R, G, B triples which come closest to the desired color and lightness.</p>
<ol>
<li>Create an empty mapping M which maps from pairs of CbCr values to quadruples of Y, R, G and B.</li>
<li>For each color R, G, B from the input palette:
<ol>
<li>Calculate Y, Cb and Cr from R, G, B as described in <link url='#algorithm-rgb2cbcr'>RGB to YCbCr</link>.</li>
<li>Round Cb and Cr to two decimal places as Cb' and Cr'.</li>
<li>If the (Cb', Cr') pair is not in the mapping M yet, or if the Y value of the existing entry is farther away from 0.732 than the new Y value, put the Y, R, G, and B values as value for the (Cb', Cr') pair into the mapping.</li>
</ol>
</li>
<li>Strip the Y values from the values of mapping M.</li>
<li>Return M as the result of the algorithm.</li>
</ol>
</section2>
<section2 topic='Mapping of a CbCr color to closest palette color' anchor='algorithm-mappalette'>
<p>Input: A set of colors (the palette) as tuples of Cbp and Crp and a color to map to the closest palette color as Cb and Cr value.</p>
<p>Output: A palette color as Cbr and Crr values.</p>
<ol>
<li>For each color as pair Cbp, Crp in the palette, calculate the distance metric: <code>D = sqrt((Cbp-Cb)*(Cbp-Cb) + (Crp-Cr)*(Crp-Cr))</code>.</li>
<li>Pick the palette color Cbp, Crp with the smallest distance metric D as result color Cbr, Crr.</li>
</ol>
<p>Note: the distance metric is simply the euclidian distance in the CbCr plane.</p>
</section2>
<section2 topic='Test Vectors' anchor='algorithm-testvector'>
<p>This section holds test vectors for the different configurations. The test vectors are provided as Comma Separated Values. Strings are enclosed by single quotes (&apos;). The first line contains a header. Each row contains, in that order, the original text, the text encoded as UTF-8 as hexadecimal octets, and the Cb, Cr, Red, Green, and Blue values.</p>
<section3 topic='No &cvd; correction' anchor='algorithm-testvector-no-cvd'>
<code><![CDATA[
text,hextext,angle,cb,cr,r,g,b
'Romeo','526f6d656f',2.099189,-0.291880,0.500000,1.000,0.475,0.215
'juliet@capulet.lit','6a756c69657440636170756c65742e6c6974',5.830846,0.500000,-0.242972,0.391,0.733,1.000
'😺','f09f98ba',4.312757,-0.211180,-0.500000,0.031,1.000,0.358]]></code>
</section3>
<section3 topic='With Red/Green-blindess correction' anchor='algorithm-testvector-cvd-redgreen'>
<code><![CDATA[text,hextext,angle,cb,cr,r,g,b
'Romeo','526f6d656f',1.049594,0.287079,0.500000,1.000,0.276,1.000
'juliet@capulet.lit','6a756c69657440636170756c65742e6c6974',2.915423,-0.500000,0.115053,0.893,0.822,0.000
'😺','f09f98ba',2.156378,-0.331588,0.500000,1.000,0.489,0.144]]></code>
</section3>
<section3 topic='With Blue-blindess correction' anchor='algorithm-testvector-cvd-blue'>
<code><![CDATA[
text,hextext,angle,cb,cr,r,g,b
'Romeo','526f6d656f',2.620391,-0.500000,0.287079,1.000,0.699,0.000
'juliet@capulet.lit','6a756c69657440636170756c65742e6c6974',4.486219,-0.115053,-0.500000,0.031,1.000,0.528
'😺','f09f98ba',3.727175,-0.500000,-0.331588,0.267,1.000,0.000]]></code>
</section3>
<section3 topic='Mapping to 216 color palette' anchor='algorithm-testvector-palette'>
<p>The used palette can be generated by sampling the RGB cube evenly with six samples on each axis (resulting in 216 colors). The resulting palette is commonly known as the palette of so-called "Web Safe" colors.</p>
<section4 topic='No &cvd; correction' anchor='algorithm-testvector-palette-no-cvd'>
<code><![CDATA[
text,hextext,angle,cb,cr,r,g,b
'Romeo','526f6d656f',2.099189,-0.291880,0.500000,1.000,0.200,0.000
'juliet@capulet.lit','6a756c69657440636170756c65742e6c6974',5.830846,0.500000,-0.242972,0.000,0.200,1.000
'😺','f09f98ba',4.312757,-0.211180,-0.500000,0.000,1.000,0.200]]></code>
</section4>
<section4 topic='With Red/Green-blindess correction' anchor='algorithm-testvector-palette-cvd-redgreen'>
<code><![CDATA[
text,hextext,angle,cb,cr,r,g,b
'Romeo','526f6d656f',1.049594,0.287079,0.500000,1.000,0.000,0.800
'juliet@capulet.lit','6a756c69657440636170756c65742e6c6974',2.915423,-0.500000,0.115053,1.000,1.000,0.000
'😺','f09f98ba',2.156378,-0.331588,0.500000,1.000,0.200,0.000]]></code>
</section4>
<section4 topic='With Blue-blindess correction' anchor='algorithm-testvector-palette-cvd-blue'>
<code><![CDATA[
text,hextext,angle,cb,cr,r,g,b
'Romeo','526f6d656f',2.620391,-0.500000,0.287079,1.000,0.600,0.000
'juliet@capulet.lit','6a756c69657440636170756c65742e6c6974',4.486219,-0.115053,-0.500000,0.000,1.000,0.400
'😺','f09f98ba',3.727175,-0.500000,-0.331588,0.200,1.000,0.000]]></code>
</section4>
</section3>
</section2>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<section2 topic='Gamma Correction' anchor='impl-gamma'>
<p>An implementation may choose a different value for Y depending on whether the sink for the R, G and B values expects Gamma Encoded or Gamma Decoded values. The recommended default of 0.732 is 0.5 to the power of 0.45, that is, a Gamma Encoded 0.5.</p>
<p>Modifications to Y SHOULD NOT be used to correct for bright/dark backgrounds. Implementations SHOULD instead use the algorithm described in <link url='#algorithm-bg'>Adapting the Color for specific Background Colors</link> for that.</p>
</section2>
</section1>
<section1 topic='Accessibility Considerations' anchor='access'>
<p>As outlined above, implementations MUST offer the &rgblind; and &bblind; corrections as defined in the <link url='#algorithm-cvd'>Corrections for &cvds;</link> section. Users MUST be allowed to choose between:</p>
<ul>
<li>disabling all corrections (skip the Corrections for &cvds; step entirely),</li>
<li>applying one of the &cvd; correction profiles and</li>
<li>disabling colorization altogether.</li>
</ul>
<p>The last option is important for users with monochromatic view.</p>
<p>Some sources on the internet indicate that people with &cvds; may profit from having larger areas of color to be able to recognize them. This should be taken into consideration when selecting font weights and line widths for colored parts.</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>This specification extracts a bit more information from an entity and shows it alongside the existing information to the user. As the algorithm is likely to produce different colors for look-alikes (see &xep0165; for examples) in JIDs, it may add additional protection against attacks based on those.</p>
<p>Due to the limited set of distinguishable colors, possible &cvds; and/or use of palettes, entities MUST NOT rely on colors being unique in any context.</p>
</section1>
<section1 topic='Design Considerations' anchor='design'>
<p>This section provides an overview of design considerations made while writing this specification. It shows alternatives which have been considered, and eventually rejected.</p>
<section2 topic='Other variants of the YCbCr color space' anchor='design-other-ycbcr'>
<p>The other common YCbCr variants, BT.709 and BT.2020, do not achieve a brightness across the color space as uniform as BT.601 does. Adapting the Y value for uniform luminosity across the range for CbCr would have complicated the algorithm with little or no gain.</p>
</section2>
<section2 topic='Hue-Saturation-Value/Lightness color space' anchor='design-hsv'>
<p>The HSV and HSL color spaces fail to provide uniform luminosity with fixed value/lightness and saturation parameters. Adapting those parameters for uniform luminosity across the hue range would have complicated the algorithm with litte to no gain.</p>
</section2>
<section2 topic='Palette-based and context-aware coloring' anchor='design-context'>
<p>Given a fixed-size and finite palette of colors, it would be possible to ensure that, until the number of entities to color exceeds the number of colors, no color collisions happen.</p>
<p>There are issues with this approach when the set of entities is dynamic. In such cases, it is possible that an entity changes its associated color (for example by re-joining a colored group chat), which defeats the original purpose.</p>
<p>In addition, more state needs to be taken into account, increasing the complexity of choosing a color.</p>
</section2>
<section2 topic='Choice of mixing function in angle generation' anchor='design-mixing'>
<p>This specification needs to collapse an arbitrarily long string into just a few bits (the angle in the CbCr plane). To do so, a CRC32 sum is used.</p>
<p>An alternative, which may yield better distribution of colors, would have been to use a cryptographic hash function. However, the performance and implementation cost for a cryptographic hash function is considerable compared with a simple CRC32, especially on small (less than 1 kiB) inputs.</p>
</section2>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;. </p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>This document requires no interaction with the &REGISTRAR;. </p>
</section1>
<section1 topic='Acknowledgements' anchor='acknowledgements'>
<p>Thanks to Daniel Gultsch, Georg Lukas, and Tobias Markmann.</p>
</section1>
</xep>

View File

@ -149,15 +149,20 @@
<p>To signal the type of communication that is desired, the entity that first decloaks MAY include a 'reason' attribute on the &lt;decloak/&gt; element. The following values for the 'reason' attribute are defined:</p>
<dl>
<dt>media</dt>
<dd>Presence is requested for a voice and/or video call, e.g. via &xep0167;.</dd>
<di>
<dt>media</dt>
<dd>Presence is requested for a voice and/or video call, e.g. via &xep0167;.</dd>
</di>
<dt>text</dt>
<di>
<dt>text</dt>
<dd>Presence is requested for a plaintext or &xep0071; conversation, e.g. with end-to-end encryption (which requires capabilities to be disclosed).</dd>
</di>
<dd>Presence is requested for a plaintext or &xep0071; conversation, e.g. with end-to-end encryption (which requires capabilities to be disclosed).</dd>
<dt>file</dt>
<dd>Presence is requested for one or more file transfers, e.g. via &xep0234; or &xep0095;.</dd>
<di>
<dt>file</dt>
<dd>Presence is requested for one or more file transfers, e.g. via &xep0234; or &xep0095;.</dd>
</di>
</dl>
<p>Inclusion of the 'reason' attribute can be interpreted by the receiving client as a signal that communication is about to start; for instance, a call accept/reject dialog could double as a UI for accepting or rejecting a decloaking request.</p>

View File

@ -357,7 +357,7 @@
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>If a MUC service supports distributed rooms, it MUST return a feature of "urn:xmpp:dmuc:0" &NSVER; in response to &xep0030; information requests.</p>
<p>If a MUC service supports distributed rooms, it MUST return a feature of "urn:xmpp:dmuc:0" in response to &xep0030; information requests.</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>

View File

@ -54,7 +54,7 @@
</p>
</section2>
<section2 topic='Requirements' anchor='reqs'>
<p>The following is a list of goals for the design of this extension:
<p>The following is a list of goals for the design of this extension:</p>
<ul>
<li>DMUC should be transparent to the end user</li>
<li>DMUC should be transparent to the client program</li>
@ -63,35 +63,33 @@
<li>Mirrors of the master room will not communicate directly with each other</li>
<li>If the S2S link is broken, it will appear to a user as if other users have left the room</li>
<li>Users in the same mirror can communicate with each other until the link is re-established with the master</li>
<li>DMUC will improve upon the &xep0033; concept</li> by eliminating the need for &lt;addresses/&gt;
<li>DMUC will improve upon the &xep0033; concept by eliminating the need for &lt;addresses/&gt;</li>
</ul>
</p>
</section2>
</section1>
<section1 topic='Terminology' anchor='terms'>
<section2 topic='General Terms' anchor='genterms'>
<dl>
<dt>master</dt>
<dd>The the actual MUC server</dd>
<dt>mirror</dt>
<dd>A mirror for a master MUC room on another machine</dd>
<di><dt>master</dt>
<dd>The the actual MUC server</dd></di>
<di><dt>mirror</dt>
<dd>A mirror for a master MUC room on another machine</dd></di>
</dl>
</section2>
<section2 topic='Actors' anchor='actors'>
<p>The following JIDs are used in this document.</p>
<dl>
<dt>fairfax.tridsys.com</dt><dd>XMPP server where the master MUC room is located</dd>
<dt>conference.fairfax.tridsys.com</dt><dd>MUC service on fairfax.tridsys.com.</dd>
<dt>chatroom@conference.fairfax.tridsys.com</dt><dd>MUC room.</dd>
<dt>kevin@fairfax.tridsys.com</dt><dd>User on fairfax.tridsys.com</dd>
<dt>scott@fairfax.tridsys.com</dt><dd>Another user on fairfax.tridsys.com</dd>
<br/>
<dt>raleigh.tridsys.com</dt><dd>A remote service, connected to fairfax.tridsys.com over constrained link</dd>
<dt>mirror.raleigh.tridsys.com</dt><dd>DMUC service on raleigh.tridsys.com</dd>
<dt>wayne@raleigh.tridsys.com</dt><dd>User on raleigh.tridsys.com</dd>
<dt>keith@raleigh.tridsys.com</dt><dd>Another user on raleigh.tridsys.com</dd>
<di><dt>fairfax.tridsys.com</dt><dd>XMPP server where the master MUC room is located</dd></di>
<di><dt>conference.fairfax.tridsys.com</dt><dd>MUC service on fairfax.tridsys.com.</dd></di>
<di><dt>chatroom@conference.fairfax.tridsys.com</dt><dd>MUC room.</dd></di>
<di><dt>kevin@fairfax.tridsys.com</dt><dd>User on fairfax.tridsys.com</dd></di>
<di><dt>scott@fairfax.tridsys.com</dt><dd>Another user on fairfax.tridsys.com</dd></di>
<di><dt>raleigh.tridsys.com</dt><dd>A remote service, connected to fairfax.tridsys.com over constrained link</dd></di>
<di><dt>mirror.raleigh.tridsys.com</dt><dd>DMUC service on raleigh.tridsys.com</dd></di>
<di><dt>wayne@raleigh.tridsys.com</dt><dd>User on raleigh.tridsys.com</dd></di>
<di><dt>keith@raleigh.tridsys.com</dt><dd>Another user on raleigh.tridsys.com</dd></di>
</dl>
<p></p>
</section2>
@ -105,7 +103,7 @@ Support for Distributed MUC in a given server instance SHOULD be determined usin
A conforming server MUST respond to disco#info requests.
</p>
<section3 topic='Disco to determine support' anchor='disco2'>
To determine if a server or service supports Distributed MUC, the requesting entity SHOULD send a disco#info request to it.
<p>To determine if a server or service supports Distributed MUC, the requesting entity SHOULD send a disco#info request to it.</p>
<example caption='Disco request for distributed MUC support'><![CDATA[
<iq type='get'
from='raleigh.tridsys.com'

View File

@ -2,6 +2,7 @@
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>

View File

@ -5,6 +5,7 @@
<!ENTITY DATETIME "<span class='ref'><link url='http://tools.ietf.org/html/rfc3339'>DATETIME</link></span> <note>RFC 3339: Date and Time on the Internet Timestamps &lt;<link url='http://tools.ietf.org/html/rfc3339'>http://tools.ietf.org/html/rfc3339</link>&gt;.</note>" >
<!ENTITY XMLDSIG "<span class='ref'><link url='http://www.w3.org/TR/xmldsig-core/'>XMLDSIG</link></span> <note>XML Signature Syntax and Processing, W3C Recommendation, 10 June 2008 &lt;<link url='http://www.w3.org/TR/xmldsig-core/'>http://www.w3.org/TR/xmldsig-core/</link>&gt;.</note>" >
<!ENTITY E2EEncrypt "<span class='ref'><link url='http://datatracker.ietf.org/doc/draft-miller-3923bis'>E2EEncrypt</link></span> <note>End-to-End Object Encryption for the Extensible Messaging and Presence Protocol (XMPP), Miller, M. and P. Saint-Andre, work in progress &lt;<link url='http://datatracker.ietf.org/doc/draft-miller-3923bis'>http://datatracker.ietf.org/doc/draft-miller-3923bis</link>&gt;.</note>" >
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='../xep.xsl'?>

View File

@ -13,8 +13,8 @@
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<approver>Council</approver>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0096</spec>

View File

@ -20,6 +20,7 @@
<header>
<title>Instant Gaming</title>
<abstract>This document defines an XMPP protocol extension for serverless instant gaming in a one-to-one context.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
@ -53,7 +54,6 @@
<initials>tg</initials>
<remark><p>First draft.</p></remark>
</revision>
&LEGALNOTICE;
</header>
<section1 topic='Introduction' anchor='intro'>
<p>

View File

@ -367,7 +367,7 @@
</tr>
</table>
</section2>
<section2 topic='Unsubscribing a subscription' anhor='unsubscribe'>
<section2 topic='Unsubscribing a subscription' anchor='unsubscribe'>
<p>
To unsubscribe a subscription, send the <strong>unsubscribe</strong> element in a request to the Thing with the <strong>seqnr</strong> sequence number corresponding to the
subscription. The Thing responds with an empty response to acknowledge the un-subscription, regardless if the subscription existed or not.
@ -726,4 +726,4 @@
</li>
</ul>
</section1>
</xep>
</xep>

302
inbox/jet.xml Normal file
View File

@ -0,0 +1,302 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY secret "&lt;secret/&gt;">
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Jingle Encrypted Transports</title>
<abstract>This specification defines a method that allows to use established encryption schemes for end-to-end encryption of Jingle transports.</abstract>
&LEGALNOTICE;
<number>XXXX</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XEP-0234</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>jet</shortname>
<schemaloc>
<ns>jingle</ns>
<url>http://xmpp.org/schemas/jingle.xsd</url>
</schemaloc>
<schemaloc>
<ns>jingle:errors</ns>
<url>http://xmpp.org/schemas/jingle-errors.xsd</url>
</schemaloc>
<registry/>
<discuss>jingle</discuss>
<author>
<firstname>Paul</firstname>
<surname>Schaub</surname>
<email>vanitasvitae@riseup.net</email>
<jid>vanitasvitae@jabberhead.tk</jid>
</author>
<revision>
<version>0.0.1</version>
<date>2017-06-12</date>
<initials>vv</initials>
<remark><p>First draft</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>Jingle Encrypted Transports (JET) strives to provide a modular and easily extensible way to wrap Jingle Transports in an additional end-to-end encryption layer. The focus of this specification lays on being modular. It should be possible to extend existing Jingle use scenarios with end-to-end encryption by simply adding a JET element to the negotiation.</p>
</section1>
<section1 topic='Terminology' anchor='terminology'>
<p>JET uses multiple encryption layers, so it is necessary to declare a distinct denomination for the different keys involved.</p>
<table caption='Denomination of keys used in the protocol'>
<tr>
<th>Designation</th>
<th>Abbrevation</th>
<th>Usage</th>
</tr>
<tr>
<td>Transport Key</td>
<td>TK</td>
<td>(Symmetric) key that is used to encrypt/decrypt the bytestreams sent/received through Jingle transports. This key encrypts the data two entities want to exchange. Examples for TK can be found under <link url='#ciphers'>"Ciphers"</link>.</td>
</tr>
<tr>
<td>Initialization Vector</td>
<td>IV</td>
<td>Initialization vector that is used together with TK.</td>
</tr>
<tr>
<td>Transport Secret</td>
<td>TS</td>
<td>Serialization of TK and TI.</td>
</tr>
<tr>
<td>Envelope Element</td>
<td>EE</td>
<td>Output element of an established end-to-end encryption method when encrypting TS.</td>
</tr>
</table>
</section1>
<section1 topic='Principle' anchor='principle'>
<p>Lets assume Romeo wants to initiate an encrypted Jingle session with Juliet. Prior to the Jingle session initiation, an already existing, established and (ideally) authenticated end-to-end encryption session between Romeo and Juliet MUST exist. This session is needed to transfer the Transport Secret from Romeo to Juliet.</p>
<p>When this precondition is met, Romeo initially generates a transport key (TK) and associated initialization vector (IV). These will later be used by the sender to encrypt, and respectively by the recipient to decrypt data that is exchanged. This protocol defines a set of usable <link url='#ciphers'>ciphers</link> from which Romeo might choose. TK and IV are serialized to create the transport secret (TS).</p>
<p>Next Romeo uses her established encryption session with Juliet to encrypt TS. The resulting envelope element (EE) will be part of the Jingle session initiation as child of the JET &secret; element.</p>
<p>When Juliet receives Romeos session request, she decrypts EE to retrieve TS, from which she can deserialize TK and IV. Now she and Romeo can go on with the session negotiation. Once the session is established, data can be encrypted and exchanged. Both parties MUST keep a copy of TS in cache until the Jingle session is ended.</p>
</section1>
<section1 topic='Encrypted Jingle File Transfer using JET' anchor='jft'>
<p>&xep0234; has the disadvantage, that transmitted files are not encrypted (aside from regular TLS transport encryption), which means that intermediate nodes like XMPP/proxy server(s) have access to the transferred data. Considering that end-to-end encryption becomes more and more important to protect free speech and personal expression, this is a major flaw that needs to be addressed.</p>
<p>In order to initiate an encrypted file transfer, the initiator includes a JET &secret; in the Jingle file transfer request.</p>
<section2 topic='File Offer'>
<p>In this scenario Romeo wants to send an encrypted text file over to Juliet. First, he generates a fresh AES-256 transport key and IV. TK and IV are serialized into TS which is then encrypted using Romeos end-to-end-encryption session with Juliet.</p>
<p>The resulting envelope element (EE) is sent as part of the security element along with the rest of the jingle stanza over to Juliet.</p>
<example caption="Romeo initiates an encrypted file offer"><![CDATA[
<iq from='romeo@montague.example/dr4hcr0st3lup4c'
id='nzu25s8'
to='juliet@capulet.example/yn0cl4bnw0yr3vym'
type='set'>
<jingle xmlns='urn:xmpp:jingle:1'
action='session-initiate'
initiator='romeo@montague.example/dr4hcr0st3lup4c'
sid='851ba2'>
<content creator='initiator' name='a-file-offer' senders='initiator'>
<description xmlns='urn:xmpp:jingle:apps:file-transfer:5'>
<file>
<date>1969-07-21T02:56:15Z</date>
<desc>This is a test. If this were a real file...</desc>
<media-type>text/plain</media-type>
<name>test.txt</name>
<range/>
<size>6144</size>
<hash xmlns='urn:xmpp:hashes:2'
algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash>
</file>
</description>
<transport xmlns='urn:xmpp:jingle:transports:s5b:1'
mode='tcp'
sid='vj3hs98y'>
<candidate cid='hft54dqy'
host='192.168.4.1'
jid='romeo@montague.example/dr4hcr0st3lup4c'
port='5086'
priority='8257636'
type='direct'/>
</transport>
<security xmlns='urn:xmpp:jingle:jet:0'
name='a-file-offer'
cipher='urn:xmpp:ciphers:aes-256-gcm-nopadding'
type='urn:xmpp:encryption:stub:0'>
<encrypted xmlns='urn:xmpp:encryption:stub:0'>
<payload>BASE64-ENCODED-ENCRYPTED-SECRET</payload>
</encrypted>
</security>
</content>
</jingle>
</iq>]]></example>
<p>Juliet decrypts the envelope element (EE) using her session with Romeo to retrieve TS from which she deserializes TK and IV. Both Juliet and Romeo then carry on with the session negotiation as described in &xep0234;. Before Romeo starts transmitting the file, he encrypts it using TK and IV. He then transmitts the encrypted file over to Juliet.</p>
<p>When Juliet received the file, she uses the TK and IV to decrypt the received file.</p>
</section2>
<section2 topic='File Request'>
<p>Juliet might want to request a file transfer from Romeo. This can be the case, when Romeo hosts the file. In order to do so, she sends generates TK and IV, creates TS from those and encrypts TS with an encryption method of her choice to get EE. TK and IV will be used by Romeo to encrypt the requested file before sending it to Juliet.</p>
<example caption="Juliet initiates an encrypted file request"><![CDATA[
<iq from='juliet@capulet.example/yn0cl4bnw0yr3vym'
id='wsn361c3'
to='romeo@montague.example/dr4hcr0st3lup4c'
type='set'>
<jingle xmlns='urn:xmpp:jingle:1'
action='session-initiate'
initiator='juliet@capulet.example/yn0cl4bnw0yr3vym'
sid='uj3b2'>
<content creator='initiator' name='a-file-request' senders='responder'>
<description xmlns='urn:xmpp:jingle:apps:file-transfer:5'>
<file>
<hash xmlns='urn:xmpp:hashes:2'
algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash>
</file>
</description>
<transport xmlns='urn:xmpp:jingle:transports:s5b:1'
mode='tcp'
sid='xig361fj'>
<candidate cid='ht567dq'
host='192.169.1.10'
jid='juliet@capulet.example/yn0cl4bnw0yr3vym'
port='6539'
priority='8257636'
type='direct'/>
</transport>
<security xmlns='urn:xmpp:jingle:jet:0'
name='a-file-request'
cipher='urn:xmpp:ciphers:aes-256-gcm-nopadding'
type='urn:xmpp:encryption:stub:0'>
<encrypted xmlns='urn:xmpp:encryption:stub:0'>
<payload>BASE64-ENCODED-ENCRYPTED-SECRET</payload>
</encrypted>
</security>
</content>
</jingle>
</iq>]]></example>
</section2>
<section2 topic='Encrypted Ranged Transfers'>
<p>&xep0234; defines a way for parties to request ranged transfers. This can be used to resume interrupted transfers etc. In case of an interrupted transfer, the receiving party might be able to decrypt parts of the received file. When requesting a resumption of the transfer, the recipient therefore can use the index of the last successfully decrypted byte of the file as offset in the ranged transfer. Since a resumed transfer takes place in a new session, the old transport secret might no longer be available to either party. For that reason the receiver creates a new TS for the session-initiation. The sending party then encrypts and sends only the requested parts of the file.</p>
<example caption="Romeo requests the resumption of an interrupted transfer using a fresh transport secret"><![CDATA[
<iq from='romeo@montague.example/dr4hcr0st3lup4c'
id='wsn361c3'
to='juliet@capulet.example/yn0cl4bnw0yr3vym'
type='set'>
<jingle xmlns='urn:xmpp:jingle:1'
action='session-initiate'
initiator='romeo@montague.example/dr4hcr0st3lup4c'
sid='uj3b2'>
<content creator='initiator' name='restart' senders='responder'>
<description xmlns='urn:xmpp:jingle:apps:file-transfer:5'>
<file>
<range offset='270336'/>
<hash xmlns='urn:xmpp:hashes:2'
algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash>
</file>
</description>
<transport xmlns='urn:xmpp:jingle:transports:s5b:1'
mode='tcp'
sid='vj3hs98y'>
<candidate cid='hft54dqy'
host='192.168.4.1'
jid='romeo@montague.example/dr4hcr0st3lup4c'
port='5086'
priority='8257636'
type='direct'/>
<candidate cid='hutr46fe'
host='24.24.24.1'
jid='romeo@montague.example/dr4hcr0st3lup4c'
port='5087'
priority='8258636'
type='direct'/>
</transport>
<security xmlns='urn:xmpp:jingle:jet:0'
name='restart'
cipher='urn:xmpp:ciphers:aes-256-gcm-nopadding'
type='urn:xmpp:encryption:stub:0'>
<encrypted xmlns='urn:xmpp:encryption:stub:0'>
<payload>BASE64-ENCODED-ENCRYPTED-SECRET</payload>
</encrypted>
</security>
</content>
</jingle>
</iq>]]></example>
</section2>
</section1>
<section1 topic='Ciphers' anchor='ciphers'>
<p>In order to encrypt the transported bytestream, the initiator must transmit a cipher key to the responder. There are multiple options available:</p>
<table caption='Available ciphers, configurations and their namespaces'>
<tr>
<th>Namespace</th>
<th>Type</th>
<th>Length (bits)</th>
<th>Parameters</th>
<th>Serialization</th>
</tr>
<tr>
<td>urn:xmpp:ciphers:aes-128-gcm-nopadding:0</td>
<td>AES</td>
<td>128</td>
<td>GCM/NoPadding</td>
<td>128BitKey::96BitIV</td>
</tr>
<tr>
<td>urn:xmpp:ciphers:aes-256-gcm-nopadding:0</td>
<td>AES</td>
<td>256</td>
<td>GCM/NoPadding</td>
<td>256BitKey::96BitIV</td>
</tr>
</table>
<p>The column 'serialization' describes, how the key and iv are serialized. "::" means plain concatenation of byte arrays.</p>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>To advertise its support for the Jingle Encrypted Transports, when replying to service discovery information ("disco#info") requests an entity MUST return URNs for any version, or extension of this protocol that the entity supports -- e.g., "urn:xmpp:jingle:jet:0" for this version, or "urn:xmpp:jingle:jet-stub:0" for a stub encryption method &VNOTE;.</p>
<example caption="Service discovery information request"><![CDATA[
<iq from='romeo@montague.example/dr4hcr0st3lup4c'
id='uw72g176'
to='juliet@capulet.example/yn0cl4bnw0yr3vym'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]></example>
<example caption="Service discovery information response"><![CDATA[
<iq from='juliet@capulet.example/yn0cl4bnw0yr3vym'
id='uw72g176'
to='romeo@montague.example/dr4hcr0st3lup4c'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<feature var='urn:xmpp:jingle:jet:0'/>
<feature var='urn:xmpp:jingle:jet-stub:0'/>
</query>
</iq>]]></example>
<p>In order for an application to determine whether an entity supports this protocol, where possible it SHOULD use the dynamic, presence-based profile of service discovery defined in &xep0115;. However, if an application has not received entity capabilities information from an entity, it SHOULD use explicit service discovery instead.</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>The initiator SHOULD NOT use the generated key TK as IV, but instead generate a seperate random IV.</p>
<p>Instead of falling back to unencrypted transfer in case something goes wrong, implementations MUST instead abort the Jingle session, informing the user.</p>
<p>IMPORTANT: This approach does not deal with metadata. In case of &xep0234;, an attacker with access to the sent stanzas can for example still see the name of the file and other information included in the &lt;file/&gt; element.</p>
<p>The responder MUST check, whether the envelope element belongs to the initiator to prevent MitM attacks</p>
</section1>
<section1 topic='Open Questions'>
<p>This is only a rough draft and there is still a ton of questions left to be answered. Here is a small non-exhaustive list of things I can think of:</p>
<ul>
<li>How exactly are interrupted transfers resumed? How (long) are keys/IVs cached?</li>
<li>May it be desirable to split data into chunks?</li>
<li>Please add to this list :)</li>
</ul>
</section1>
<section1 topic='TODO'>
<ul>
<li>Split up the protocol into encryption method specific sub protocols (jet-omemo, jet-ox...)</li>
</ul>
</section1>
</xep>

View File

@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
@ -35,7 +36,7 @@
</section1>
<section1 topic='Protocol'>
<para>The basic flow is as follows.</para>
<p>The basic flow is as follows.</p>
<code><![CDATA[
Initiator Responder
| |

View File

@ -31,7 +31,7 @@
</dependencies>
<supersedes/>
<supersededby/>
<shortname/>Jingle Nodes <author>
<shortname>Jingle Nodes</shortname> <author>
<firstname>Thiago</firstname>
<surname>Camargo</surname>
<email>thiago@xmppjingle.com</email>
@ -120,7 +120,7 @@ All signalling, request, response and publishing is done via XMPP, not requiring
<tracker policy='public' address='capulet.lit' protocol='udp'/>
</services>
</iq> ]]></example>
<em>In this example 'montague.lit' XMPP Domain a Relay Service and a Tracker Service. The Relay Service can be contacted in order to retrieve Relay Channels. The Tracker Service can be contacted in order to retrieve its known services.</em>
<p><em>In this example 'montague.lit' XMPP Domain a Relay Service and a Tracker Service. The Relay Service can be contacted in order to retrieve Relay Channels. The Tracker Service can be contacted in order to retrieve its known services.</em></p>
</section2>
<section2 topic="Jingle Client Searches for Services on a Retrieved Tracker Service" anchor="clientcheckownserver">
<p>A Jingle Client MAY NOT be satisfied with only one Relay Service entry found. So it keeps the search on the known Tracker Services.</p>
@ -139,7 +139,7 @@ All signalling, request, response and publishing is done via XMPP, not requiring
type='result'>
<services xmlns='http://jabber.org/protocol/jinglenodes'/>
</iq> ]]></example>
<em>In this example 'capulet.lit' returned an empty service list, meaning that it does NOT known ANY Relay or Tracker Services.</em>
<p><em>In this example 'capulet.lit' returned an empty service list, meaning that it does NOT known ANY Relay or Tracker Services.</em></p>
</section2>
<section2 topic="Jingle Client Searches for Services on online Roster Entries" anchor="clientcheckownserver">
<p>A Jingle Client MAY NOT be satisfied with only one Relay Service entry found. So it keeps the search on his Roster Items until find the desired amount of Relay Services, or while it does NOT exceed a search depth or ANY other Client implementation policy. The Client SHOULD keep a list of visited Tracker Services in order to avoid searching twice in same Service Entity.</p>
@ -161,7 +161,7 @@ All signalling, request, response and publishing is done via XMPP, not requiring
</services>
</iq> ]]></example>
<p>In this example 'juliet@capulet.lit/balcony' returned a Relay Service entry that is restricted to its roster. This Service is usable as the requester has 'juliet@capulet.lit/balcony' on its roster. Although, services with policy 'roster' MUST NOT be listed in Tracker Responses expects in Tracker Responses that comes from the Service Entity itself, in this case 'juliet@capulet.lit/balcony'.</p>
<em>In the presented example 'romeo@montague.lit/orchard' knows that 'juliet@capulet.lit/balcony' provides Relay Service, but if another entity requests 'romeo@montague.lit/orchard' its known services, it MUST NOT include 'juliet@capulet.lit/balcony' as it is a roster restricted entry.</em>
<p><em>In the presented example 'romeo@montague.lit/orchard' knows that 'juliet@capulet.lit/balcony' provides Relay Service, but if another entity requests 'romeo@montague.lit/orchard' its known services, it MUST NOT include 'juliet@capulet.lit/balcony' as it is a roster restricted entry.</em></p>
</section2>
<section2 topic="Jingle Client Consuming the Relay Service" anchor="clientconsumingrelay">
<p>A Jingle Client with direct access to a public IP can potentially provide the Relay Service becaming itself a Jingle Relay Node. The service can intend to provide a public service, or a restricted services based on user preferences, like buddylist, whitelist, blacklist, domain, etc...</p>
@ -372,15 +372,9 @@ All signalling, request, response and publishing is done via XMPP, not requiring
<p>Relay Channels auto expires MUST expire on traffic inactivity. The inactivity timeout recommended is 60 seconds.</p>
<p>It is heavily recommended that the Super Node implements throttle:</p>
<ul>
<p>
<li>Based on JID, allowing the control of how many concurrent channels an specific JID can have.</li>
</p>
<p>
<li>Based on JID, allowing the control of how many channel requests an specific JID can request in a time period.</li>
</p>
<p>
<li>Based on Bandwidth, allowing the control of how much bandwidth a channel can use. The maximum bandwidth SHOULD be included on the candidate element provided by a Super Node on the attribute maxkbps. If no attribute is present, it means that it has no bandwidth control.</li>
</p>
<li>Based on Bandwidth, allowing the control of how much bandwidth a channel can use. The maximum bandwidth SHOULD be included on the candidate element provided by a Super Node on the attribute maxkbps. If no attribute is present, it means that it has no bandwidth control.
<example caption="Channel Returned by a Node with bandwidth throttle (stub)"><![CDATA[
<channel component='1'
id='el0747fg11'
@ -389,7 +383,7 @@ All signalling, request, response and publishing is done via XMPP, not requiring
remoteport='35802'
protocol='udp'
maxkbps='120'/>
]]></example>
]]></example></li>
</ul>
</section1>
<section1 topic='XML Schema' anchor='schema'>

View File

@ -80,7 +80,7 @@
</tr>
<tr>
<td>Good quality; optimized for voice; can be used for wide-band audio.</td>
<td>See &rtpspeex;.</td>
<td>See &rfc5574;.</td>
<td>Freely downloadable under a revised BSD license at &lt;<link url='http://speex.org/'>http://speex.org/</link>&gt; and commonly deployed on Internet (VoIP) systems; not commonly deployed on non-Internet systems.</td>
<td>Designed to be patent-clear.</td>
</tr>

View File

@ -64,7 +64,7 @@
</tr>
<tr>
<td>Good quality; optimized for voice; can be used for wide-band audio.</td>
<td>See &rtpspeex;.</td>
<td>See &rfc5574;.</td>
<td>Widely available and freely downloadable under a revised BSD license at &lt;<link url='http://speex.org/'>http://speex.org/</link>&gt;.</td>
<td>Designed to be patent-free.</td>
</tr>

View File

@ -54,7 +54,7 @@
</section1>
<section1 topic='Protocol' anchor='protocol'>
<para>The basic flow is as follows.</para>
<p>The basic flow is as follows.</p>
<code><![CDATA[
Romeo Juliet
| |

View File

@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>

View File

@ -40,7 +40,7 @@
</header>
<section1 topic='Protocol' anchor='protocol'>
<p>&xep0167; recommends the use of the Secure Real-time Transport Protocol (SRTP) for end-to-end encryption of RTP sessions negotiated using &xep0166;. An alternative approach to end-to-end encryption of RTP traffic is provided by &zrtp;. Although negotiation of ZRTP mainly occurs in the media channel rather than the signalling channel, the ZRTP specification defines one SDP attribute called "zrtp-hash" (this communicates the ZRTP version supported as well as a hash of the Hello message).</p>
<p>&xep0167; recommends the use of the Secure Real-time Transport Protocol (SRTP) for end-to-end encryption of RTP sessions negotiated using &xep0166;. An alternative approach to end-to-end encryption of RTP traffic is provided by &rfc6189;. Although negotiation of ZRTP mainly occurs in the media channel rather than the signalling channel, the ZRTP specification defines one SDP attribute called "zrtp-hash" (this communicates the ZRTP version supported as well as a hash of the Hello message).</p>
<p>The SDP format is shown below.</p>
<code>
a=zrtp-hash:zrtp-version zrtp-hash-value

View File

@ -48,13 +48,11 @@
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>The following design requirements reflect the need to offer performance as close as possible to standard XMPP-based stanza handling.</p>
<p>
<ol>
<li>JSON default character set must be UTF-8</li>
<li>JSON stanza must contain (or retain) all XMPP stanza content and hierarchy</li>
<li>Server must support both XML and JSON content-types.</li>
</ol>
</p>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<p>Intent for following use-cases is to support JavaScript-based clients which typically start XMPP-session from HTTP-dialog, and then depending on network environment and run-time support end using BOSH or C2S through Web Sockets.</p>
@ -69,23 +67,23 @@
<section1 topic='Implementation Notes' anchor='impl'>
<p>Client (and server) implementation needs to take care of using such JSON object format which retains all structure of all XMPP XML stanzas.</p>
<section2 topic='HTTP Header' anchor='http-header'>
<p>Following http-header is used to communicate with server using JSON playload:
<section3 topic='Request' anchor='c-header'><pre>
<p>Following http-header is used to communicate with server using JSON playload:</p>
<section3 topic='Request' anchor='c-header'><code>
POST /http-bind HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: application/jsonrequest
Content-Length: 230
</pre></section3>
<section3 topic='Response' anchor='s-header'><pre>
</code></section3>
<section3 topic='Response' anchor='s-header'><code>
HTTP/1.1 200 OK
Content-Type: application/jsonrequest
Content-Length: 513
</pre></section3></p>
</code></section3>
</section2>
<section2 topic='Initial BOSH request/response in JSON' anchor='init-payload'>
<p>In following example server name is modified so content length is not accurate. Also JSON payload is modified for better clarity of its structure.
<section3 topic='Client request' anchor='c-req'><pre>
<p>In following example server name is modified so content length is not accurate. Also JSON payload is modified for better clarity of its structure.</p>
<section3 topic='Client request' anchor='c-req'><code>
POST /http-bind HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
@ -106,8 +104,8 @@ Content-Length: 230
"@xmpp" : "urn:xmpp:xbosh" }
}
}
</pre></section3>
<section3 topic='Server response' anchor='s-resp'><pre>
</code></section3>
<section3 topic='Server response' anchor='s-resp'><code>
HTTP/1.1 200 OK
Content-Type: application/jsonrequest
Content-Length: 513
@ -141,140 +139,139 @@ Content-Length: 513
}
}
}
</pre></section3>
</code></section3>
<section3 topic='JSON syntax explained' anchor='json-syntax'>
<ul>
<li>Tag with text value</li>
<em>XMPP-XML:</em><pre>
<li>Tag with text value
<em>XMPP-XML:</em><code>
&lt;tag&gt;txt-value&lt;/tag&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : "txt-value" }
</pre>
<li>Tag with another tag</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with another tag
<em>XMPP-XML:</em><code>
&lt;tag&gt;
&lt;tag2&gt;txt-value&lt;/tag2&gt;
&lt;/tag&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"$" : {
"tag2" : "txt-value" }
}
}
</pre>
<li>Multiple text value tags as array</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Multiple text value tags as array
<em>XMPP-XML:</em><code>
&lt;tag&gt;
&lt;tag2&gt;txt-value1&lt;/tag2&gt;
&lt;tag2&gt;txt-value2&lt;/tag2&gt;
&lt;/tag&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"$" : {
"tag2" : [ "txt-value1", "txt-value2" ] }
}
}
</pre>
<li>Tag with attribute, no value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with attribute, no value
<em>XMPP-XML:</em><code>
&lt;tag attr="attr-value" /&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : { "attr" : "attr-value" } }
</pre>
<li>Tag with multiple attributes as array, no value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with multiple attributes as array, no value
<em>XMPP-XML:</em><code>
&lt;tag attr="attr-value1" attr="attr-value2" /&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"attr" : [ "attr-value1", "attr-value2" ] }
}
</pre>
<li>Tags as array with unique attributes, no value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tags as array with unique attributes, no value
<em>XMPP-XML:</em><code>
&lt;tag&gt;
&lt;tag2 attr="attr-value1" /&gt;
&lt;tag2 attr="attr-value2" /&gt;
&lt;/tag&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"tag2" : [
{ "attr" : "attr-value1" },
{ "attr" : "attr-value2" } ]
}
}
</pre>
<li>Tag with namespace attribute, no value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with namespace attribute, no value
<em>XMPP-XML:</em><code>
&lt;tag xmlns:ns="ns-value" /&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"xmlns" : {
"@ns" : "attr-value" }
}
}
</pre>
<li>Tag with many attributes to namespace, no value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with many attributes to namespace, no value
<em>XMPP-XML:</em><code>
&lt;tag xmlns="root-value" xmlns:ns="ns-value" /&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"xmlns" : {
"$" : "root-value",
"@ns" : "attr-value" }
}
}
</pre>
<li>Tag with namespace attribute, no value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with namespace attribute, no value
<em>XMPP-XML:</em><code>
&lt;ns:tag attr="attr-value" /&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"$$" : "ns",
"attr" : "attr-value" }
}
</pre>
<li>Tag with attribute and text value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Tag with attribute and text value
<em>XMPP-XML:</em><code>
&lt;tag attr="attr-value"&gt;txt-value&lt;/tag&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"attr" : "attr-value",
"$" : "txt-value" }
}
</pre>
<li>Namespace tag with attribute and text value</li>
<em>XMPP-XML:</em><pre>
</code></li>
<li>Namespace tag with attribute and text value
<em>XMPP-XML:</em><code>
&lt;ns:tag attr="attr-value"&gt;txt-value&lt;/tag&gt;
</pre>
<em>JSON:</em><pre>
</code>
<em>JSON:</em><code>
{ "tag" : {
"$$" : "ns",
"attr" : "attr-value",
"$" : "txt-value" }
}
</pre>
</code></li>
<li>Complex combination</li>
<li>Tag name conversions</li>
<p>JSON data is typically converted to JS-object in browser client. Practically this means that <em>tag string name</em> / <em>value string</em> pairs are converted to <em>tag name</em> / <em>value string</em> pairs. Example:<pre>
<li>Tag name conversions
<p>JSON data is typically converted to JS-object in browser client. Practically this means that <em>tag string name</em> / <em>value string</em> pairs are converted to <em>tag name</em> / <em>value string</em> pairs. Example:</p><code>
var s = '{ "key" : "value" }';
var sObj = JSON.parse(s); // sObj = { key : "value" };
var sStr = JSON.stringify(sObj); // sStr = '{"key":"value"}';
</pre></p>
</code>
<p>Javascript variable naming doesn't support full colon characters '<em>:</em>'. Intented conversion between JSON and JS-objects is based on native JavaScript class <em>JSON</em>, more spesifically methods <em>JSON.stringify()</em> for converting object to JSON, and <em>JSON.parse()</em> from JSON to object.<br/>
Because of this namespace definitions are constructed hiearchically and their scope is within tag it is defined. Currently only reserved namespace name is '<em>xml</em>'.</p>
Because of this namespace definitions are constructed hiearchically and their scope is within tag it is defined. Currently only reserved namespace name is '<em>xml</em>'.</p></li>
</ul>
</section3>
</p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>

View File

@ -66,12 +66,12 @@
<section1 topic='Introduction' anchor='intro'>
<p>
Linked Process is a protocol for Internet-scale, general-purpose distributed computing. With an implementation of this protocol, any computing device with an Internet connection can contribute computing resources to a user-generated compute cloud.
</p>
<ul>
<li>The term <strong>computing device</strong> is broad and spans particulars such as cell phones, laptops, desktops, servers, supercomputers, etc. In Linked Process, a computing device is anything that maintains a central processing unit (CPU) that can be programmed to execute any desired computation.</li>
<li>The term <strong>computing resources</strong> is broad and spans particulars such as clock cycles, data sets, software application programming interfaces (APIs), or specialized hardware componets such as cell phone cameras, field-programmable gate array (FPGA) circuits, etc.</li>
<li>The term <strong>compute cloud</strong> is the collection of all Linked Process enabled devices, their resources, and the Linked Process specific software components defined later in this specification.</li>
</ul>
</p>
<p>
Within the category of computing devices, Linked Process makes a distinction between resource consumers (devices making use of non-local computing resources) and a resource providers (devices offering computing resources)<note>Nothing prevents the same device from being a resource consumer in one context and being a resource provider in another.</note>. Linked Process allows a resource consumer to leverage the computing resources offered by a resource provider in anyway deemed appropriate by the resource consumer. This is accomplished by the resource consumer providing/migrating/sending code (i.e. software instructions) to a computer language interpreter maintained by the resource provider. As such, it is up to the resource consumer to define the instructions to be executed by the provider. Given this architecture, resource providing devices in a Linked Process cloud are general-purpose computing sandboxes (i.e. they can be leveraged for computational ends that are defined by a resource consumer).
</p>
@ -84,18 +84,18 @@
Linked Process was developed to address the following two distributed computing requirements: <em>Internet-scale</em> and <em>general-purpose</em>. These requirements imply yet more requirements which accompany their description below.
</p>
<ul>
<li><strong>Internet-scale</strong>: it is required that any device with an Internet connection (from a cell phone to a supercomputer) be able provide/contribute and consume/leverage computing resources in a Linked Process cloud.</li>
<li><strong>Internet-scale</strong>: it is required that any device with an Internet connection (from a cell phone to a supercomputer) be able provide/contribute and consume/leverage computing resources in a Linked Process cloud.
<ul>
<li><strong>Decentralized</strong>: it is required that the computing resources are not necessarily centralized or controlled by any one party.</li>
<li><strong>Discoverable</strong>: it is required that resource providers be discoverable by resources consumers.</li>
<li><strong>Transient</strong>: it is required that devices coming online and offline are gracefully incoporated and removed from the cloud.</li>
</ul>
<li><strong>General-purpose</strong>: It is required that consumers be able to utilize provided resources for any desired purpose.</li>
</ul></li>
<li><strong>General-purpose</strong>: It is required that consumers be able to utilize provided resources for any desired purpose.
<ul>
<li><strong>Language-agnostic</strong>: it is required that the protocol support the migration of code written in any computer language.</li>
<li><strong>Safe</strong>: it is required that the execution of consumer code be confined by permissions clearly specified by the resource provider<note>There is a tradeoff between "general-purpose" and "safety." It is important to ensure that the integrity of resource providers are not compomised due to malicious or poorly written code.</note>.</li>
<li><strong>Accessible</strong>: it is required that computing resources be accessible when permissions allow by ensuring the supported language interpreters provide necessary "low-level" manipulations of such resources.</li>
</ul>
</ul></li>
</ul>
</section1>
<section1 topic='Glossary' anchor='glossary'>
@ -161,18 +161,18 @@
A <tt>&lt;spawn_vm/&gt;</tt> element is wrapped by an <tt>&lt;iq/&gt;</tt> element. The purpose of <tt>&lt;spawn_vm/&gt;</tt> is to have a farm create a new virtual machine. It is through a virtual machine that a villein is able to access the computing resources of the physical device that hosts the farm (i.e. the resource provider). A virtual machine will maintain a state throughout a villein "session" with that virtual machine. The only way to alter the state of a virtual machine is through submitting jobs and updating its variable bindings<note>This is an important concept to understand. During the life of a virtual machine, the virtual machine has a state that changes as jobs are submitted and bindings are managed. In other words, a virtual machine is not a "one-job" machine.</note>.
</p>
<ul>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;spawn_vm/&gt;</tt>:</li>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;spawn_vm/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_species</tt> attribute: the language of the virtual machine to be spawned (values are implementation dependent).</li>
<li><tt>farm_password</tt> attribute: the password of the farm<note>This is an OPTIONAL attribute. Farm passwords are useful for creating private farms in order, for example, to allow "looser" permissions with known villeins. If no password is required (e.g. a public farm), then no <tt>farm_password</tt> attribute SHOULD be provided.</note>.</li>
</ul>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;spawn_vm/&gt;</tt>:</li>
</ul></li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;spawn_vm/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: a farm-internal unique identifier for the newly created virtual machine. This MUST be provided if <tt>&lt;iq type="result"/&gt;</tt>.</li>
<li><tt>vm_species</tt> attribute: the species of the newly created virtual machine. This MUST be provided if <tt>&lt;iq type="result"/&gt;</tt>.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.
<ul>
<li><tt>&lt;species_not_supported/&gt;</tt></li>
<li><tt>&lt;farm_is_busy/&gt;</tt></li>
@ -180,8 +180,8 @@
<li><tt>&lt;internal_error/&gt;</tt></li>
<li><tt>&lt;wrong_farm_password/&gt;</tt></li>
<li>if an error occurred, the farm SHOULD provide some implementation specific human-readable information detailing the error in <tt>&lt;text/&gt;</tt>. Error responses extend the requirements set forth by the <link url="http://xmpp.org/rfcs/rfc3920.html">Core</link> XMPP specification.</li>
</ul>
</ul>
</ul></li>
</ul></li>
</ul>
<example caption="A successful &lt;spawn_vm/&gt; request."><![CDATA[<iq from="lp1@linkedprocess.org/villein"
@ -218,18 +218,18 @@
A <tt>&lt;submit_job/&gt;</tt> element is wrapped by an <tt>&lt;iq/&gt;</tt> element. The purpose of <tt>&lt;submit_job/&gt;</tt> is to send code (i.e. expressions, statements, instructions) to a virtual machine for execution (i.e. evaluation, interpretation). The expression SHOULD be respective of the virtual machine's language (i.e. the virtual machine's species). If they are not, then evaluation errors SHOULD occur. The expression submitted through a <tt>&lt;submit_job/&gt;</tt> stanza can be short (e.g. set a variable value, get a variable value) or long (e.g. define a class/method, execute a long running body of statements). The submitted expression is called a <strong>job</strong> in Linked Process and is assigned a <tt>job_id</tt> as specified by the <tt>&lt;iq/&gt;</tt> <tt>id</tt> attribute value. That is, the staza id of the <tt>&lt;submit_job/&gt;</tt> is the job's id.
</p>
<ul>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;submit_job/&gt;</tt>:</li>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;submit_job/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>&lt;submit_job/&gt;</tt> text body: the expression for the virtual machine to evaluate. If no text body is provided, the expression to be evaluated can be interpreted as a blank string or a null expression. The behavior of such an evaluation is up to the virtual machine implementation.</li>
</ul>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;submit_job/&gt;</tt>:</li>
</ul></li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;submit_job/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>&lt;submit_job/&gt;</tt> text body: the result of the expression evaluated.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt><note>Note that, according to XMPP Core, it is RECOMMENDED that an <tt>&lt;iq type="error"/&gt;</tt> return the the query provided by the villein. In the example above, only the tag name is provided without the full body. The reason for this is that for <tt>&lt;submit_job/&gt;</tt>, the length of the text body of the tag is unrestricted and thus could be a very large piece of code. Thus, returning the original <tt>&lt;submit_job/&gt;</tt> stanza in the error response could lead to excessive communication overhead.</note>.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt><note>Note that, according to XMPP Core, it is RECOMMENDED that an <tt>&lt;iq type="error"/&gt;</tt> return the the query provided by the villein. In the example above, only the tag name is provided without the full body. The reason for this is that for <tt>&lt;submit_job/&gt;</tt>, the length of the text body of the tag is unrestricted and thus could be a very large piece of code. Thus, returning the original <tt>&lt;submit_job/&gt;</tt> stanza in the error response could lead to excessive communication overhead.</note>.
<ul>
<li><tt>&lt;malformed_packet/&gt;</tt></li>
<li><tt>&lt;internal_error/&gt;</tt></li>
@ -240,8 +240,8 @@
<li><tt>&lt;vm_not_found/&gt;</tt></li>
<li><tt>&lt;job_timed_out/&gt;</tt></li>
<li>if an error occurred, the farm SHOULD provide some implementation specific human-readable information detailing the error in <tt>&lt;text/&gt;</tt>. Error responses extend the requirements set forth by the <link url="http://xmpp.org/rfcs/rfc3920.html">Core</link> XMPP specification.</li>
</ul>
</ul>
</ul></li>
</ul></li>
</ul>
<example caption="A successful &lt;submit_job/&gt; request."><![CDATA[<iq from="lp1@linkedprocess.org/villein"
@ -306,30 +306,30 @@
A <tt>&lt;ping_job/&gt;</tt> element is wrapped by an <tt>&lt;iq/&gt;</tt> element. The purpose of <tt>&lt;ping_job/&gt;</tt> is to determine the status (i.e. progress, state) of a previously submitted <tt>&lt;submit_job/&gt;</tt> stanza (i.e. job) that has yet to complete.
</p>
<ul>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;ping_job/&gt;</tt>:</li>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;ping_job/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>job_id</tt> attribute: the job identifier (the job identifier is the stanza identifier of the respective <tt>&lt;submit_job/&gt;</tt>).</li>
</ul>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;ping_job/&gt;</tt>:</li>
</ul></li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;ping_job/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>status</tt> attribute: the job's status. This MUST be provided if <tt>&lt;iq type="result"/&gt;</tt>.</li>
<li><tt>status</tt> attribute: the job's status. This MUST be provided if <tt>&lt;iq type="result"/&gt;</tt>.
<ul>
<li><tt>in_progress</tt>: the job is in progress.</li>
</ul>
</ul></li>
<li><tt>job_id</tt> attribute: the job identifier for the status being reported.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.
<ul>
<li><tt>&lt;malformed_packet/&gt;</tt></li>
<li><tt>&lt;vm_not_found/&gt;</tt></li>
<li><tt>&lt;internal_error/&gt;</tt></li>
<li><tt>&lt;job_not_found/&gt;</tt></li>
<li>if an error occurred, the farm SHOULD provide some implementation specific human-readable information detailing the error in <tt>&lt;text/&gt;</tt>. Error responses extend the requirements set forth by the <link url="http://xmpp.org/rfcs/rfc3920.html">Core</link> XMPP specification.</li>
</ul>
</ul>
</ul></li>
</ul></li>
</ul>
<example caption="A successful &lt;ping_job/&gt; request."><![CDATA[<iq from="lp1@linkedprocess.org/villein"
to="lp2@linkedprocess.org/farm" type="get" id="xxxx">
@ -348,26 +348,26 @@
An <tt>&lt;abort_job/&gt;</tt> element is wrapped by an <tt>&lt;iq/&gt;</tt> element. The purpose of <tt>&lt;abort_job/&gt;</tt> is to cancel (i.e. quit, stop, halt) a previously submitted, yet not completed <tt>&lt;submit_job/&gt;</tt> stanza (i.e. job).
</p>
<ul>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;abort_job/&gt;</tt>:</li>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;abort_job/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>job_id</tt> attribute: the job identifier (the job identifier is the stanza identifier of the respective <tt>&lt;submit_job/&gt;</tt>).</li>
</ul>
</ul></li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;abort_job/&gt;</tt>:</li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;abort_job/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.
<ul>
<li><tt>&lt;malformed_packet/&gt;</tt></li>
<li><tt>&lt;vm_not_found/&gt;</tt></li>
<li><tt>&lt;internal_error/&gt;</tt></li>
<li><tt>&lt;job_not_found/&gt;</tt></li>
<li>if an error occurred, the farm SHOULD provide some implementation specific human-readable information detailing the error in <tt>&lt;text/&gt;</tt>. Error responses extend the requirements set forth by the <link url="http://xmpp.org/rfcs/rfc3920.html">Core</link> XMPP specification.</li>
</ul>
</ul>
</ul></li>
</ul></li>
</ul>
<example caption="A successful &lt;abort_job/&gt; request."><![CDATA[<iq from="lp1@linkedprocess.org/villein"
@ -403,31 +403,31 @@
A <tt>&lt;manage_bindings/&gt;</tt> element is wrapped by an <tt>&lt;iq/&gt;</tt> element. The purpose of <tt>&lt;manage_bindings/&gt;</tt> is to allow a villein to get and set variables in the variable space of a virtual machine. The definition of the "variable space" is up to the implementation of the virtual machine. In general, this is the set of all global variables for the virtual machine.
</p>
<ul>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> or <tt>&lt;iq type="set"&gt;</tt> <tt>&lt;manage_bindings/&gt;</tt>:</li>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> or <tt>&lt;iq type="set"&gt;</tt> <tt>&lt;manage_bindings/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt></li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>&lt;binding/&gt;</tt> child tag of <tt>&lt;manage_bindings/&gt;</tt> for <tt>&lt;iq type="get"/&gt;</tt></li>
<li><tt>&lt;binding/&gt;</tt> child tag of <tt>&lt;manage_bindings/&gt;</tt> for <tt>&lt;iq type="get"/&gt;</tt>
<ul>
<li><tt>name</tt> attribute: the name of the variable.</li>
</ul>
<li><tt>&lt;binding/&gt;</tt> child tag of <tt>&lt;manage_bindings/&gt;</tt> for <tt>&lt;iq type="set"/&gt;</tt></li>
</ul></li>
<li><tt>&lt;binding/&gt;</tt> child tag of <tt>&lt;manage_bindings/&gt;</tt> for <tt>&lt;iq type="set"/&gt;</tt>
<ul>
<li><tt>name</tt> attribute: the name of the variable.</li>
<li><tt>value</tt> attribute: the value of the variable.</li>
<li><tt>datatype</tt> attribute: the datatype of the variable (specified using <link url="http://www.w3.org/TR/xmlschema-2/">XML schema for datatypes</link>).</li>
</ul>
</ul>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;manage_bindings/&gt;</tt>:</li>
</ul></li>
</ul></li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;manage_bindings/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li><tt>&lt;binding/&gt;</tt> child tag of <tt>&lt;manage_bindings/&gt;</tt> for <tt>&lt;iq type="get"/&gt;</tt></li>
<li><tt>&lt;binding/&gt;</tt> child tag of <tt>&lt;manage_bindings/&gt;</tt> for <tt>&lt;iq type="get"/&gt;</tt>
<ul>
<li><tt>name</tt> attribute: the name of the variable.</li>
<li><tt>value</tt> attribute: the value of the variable.</li>
</ul>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.</li>
</ul></li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.
<ul>
<li><tt>&lt;malformed_packet/&gt;</tt></li>
<li><tt>&lt;vm_not_found/&gt;</tt></li>
@ -435,8 +435,8 @@
<li><tt>&lt;unknown_datatype/&gt;</tt></li>
<li><tt>&lt;invalid_value/&gt;</tt></li>
<li>if an error occurred, the farm SHOULD provide some implementation specific human-readable information detailing the error in <tt>&lt;text/&gt;</tt>. Error responses extend the requirements set forth by the <link url="http://xmpp.org/rfcs/rfc3920.html">Core</link> XMPP specification.</li>
</ul>
</ul>
</ul></li>
</ul></li>
</ul>
<example caption="A successful &lt;manage_bindings/&gt; set request."><![CDATA[<iq from="lp1@linkedprocess.org/villein"
to="lp2@linkedprocess.org/farm" type="set" id="xxxx">
@ -468,11 +468,11 @@
</iq>
]]></example>
<p>
After the previous <tt>&lt;manage_bindings/&gt;</tt> stanza has been processed by the virtual machine, it is possible to use the bindings in a statement. For example, in JavaScript
After the previous <tt>&lt;manage_bindings/&gt;</tt> stanza has been processed by the virtual machine, it is possible to use the bindings in a statement. For example, in JavaScript</p>
<code>var fact = name + " knows josh and peter";</code>
will set <tt>fact</tt> to the value "marko knows josh and peter" as well as make it an accessible binding.
<p>will set <tt>fact</tt> to the value "marko knows josh and peter" as well as make it an accessible binding.
</p>
<example caption="A successful &lt;manage_bindings/&gt; get request."><![CDATA[<iq from="lp1@linkedprocess.org/villein"
to="lp2@linkedprocess.org/farm" type="get" id="zzzz">
@ -490,11 +490,11 @@
</iq>
]]></example>
<p>
A useful aspect of <tt>&lt;manage_bindings/&gt;</tt> is that it can be used to track the state of a variable during the execution of a job. For example, suppose the following job is submitted to a JavaScript virtual machine.<code>var x = 1.0;
A useful aspect of <tt>&lt;manage_bindings/&gt;</tt> is that it can be used to track the state of a variable during the execution of a job. For example, suppose the following job is submitted to a JavaScript virtual machine.</p><code>var x = 1.0;
while(true) {
x = x + 0.0001;
}</code>
This job will continue indefinitely (or until it is timed out by the virtual machine). However, during its execution, it is possible to determine the current state of <tt>x</tt> using <tt>&lt;manage_bindings/&gt;</tt>. Each get-based <tt>&lt;manage_bindings/&gt;</tt> call should return a larger <tt>x</tt> value.
<p>This job will continue indefinitely (or until it is timed out by the virtual machine). However, during its execution, it is possible to determine the current state of <tt>x</tt> using <tt>&lt;manage_bindings/&gt;</tt>. Each get-based <tt>&lt;manage_bindings/&gt;</tt> call should return a larger <tt>x</tt> value.
</p>
</section3>
<section3 topic="Terminating a Virtual Machine">
@ -502,23 +502,23 @@ while(true) {
A <tt>&lt;terminate_vm/&gt;</tt> element is wrapped by an <tt>&lt;iq/&gt;</tt> element. The purpose of a <tt>&lt;terminate_vm/&gt;</tt> is to shutdown (i.e. quit, exit, halt) the virtual machine. Upon termination, the virtual machine will lose its state and will no longer be able to be communicated with.
</p>
<ul>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;terminate_vm/&gt;</tt>:</li>
<li>Villein generated <tt>&lt;iq type="get"&gt;</tt> <tt>&lt;terminate_vm/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
</ul>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;terminate_vm/&gt;</tt>:</li>
</ul></li>
<li>Farm generated <tt>&lt;iq type="result"&gt;</tt> or <tt>&lt;iq type="error"&gt;</tt> <tt>&lt;terminate_vm/&gt;</tt>:
<ul>
<li><tt>xmlns</tt> attribute: <tt>http://linkedprocess.org/2009/06/Farm#</tt>.</li>
<li><tt>vm_id</tt> attribute: the farm-internal unique identifier of the virtual machine.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.</li>
<li>One of these error conditions MUST be provided if <tt>&lt;iq type="error"/&gt;</tt>.
<ul>
<li><tt>&lt;malformed_packet/&gt;</tt></li>
<li><tt>&lt;vm_not_found/&gt;</tt></li>
<li><tt>&lt;internal_error/&gt;</tt></li>
<li>if an error occurred, the farm SHOULD provide some implementation specific human-readable information detailing the error in <tt>&lt;text/&gt;</tt>. Error responses extend the requirements set forth by the <link url="http://xmpp.org/rfcs/rfc3920.html">Core</link> XMPP specification.</li>
</ul>
</ul>
</ul></li>
</ul></li>
</ul>
<example caption="A successful &lt;terminate_vm/&gt; request."><![CDATA[<iq from="lp1@linkedprocess.org/LoPVillein/EFGH"
to="lp2@linkedprocess.org/farm" type="get" id="xxxx">
@ -928,7 +928,7 @@ while(true) {
</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
The following namespaces are defined by Linked Process:
<p>The following namespaces are defined by Linked Process:</p>
<ul>
<li><tt>http://linkedprocess.org/2006/06/Farm#</tt></li>
<li><tt>http://linkedprocess.org/2006/06/Registry#</tt></li>

View File

@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
@ -107,27 +108,27 @@
<section1 topic='Conclusions'>
<p>As with anything, there are no hard and fast rules. If there were, they might look like these. First, for devices:</p>
<dl>
<dt>Transmit no data.</dt>
<dd>Transmitting costs significant power, and moreover raises the radio state. Not transmitting will allow it to maximize the time spent in the low-cost Idle state.</dd>
<dt>If you must transmit, then transmit only a small volume.</dt>
<dd>If there is only a small amount of data transmitted - less than 128 octets typically - the radio will only raise to FACH, which is significantly cheaper than DCH.</dd>
<dt>If you must transmit, then compress as hard as possible.</dt>
<dd>Since individual octets have an associate power - and often financial - cost, it's worth maximizing the compression algorithm, even if the volume of traffic will raise to DCH.</dd>
<dt>If you have transmit a lot, then do a lot</dt>
<dd>If the radio is raised to DCH anyway, then you may as well go fetch that avatar you were missing, since you're chewing through power anyway.</dd>
<dt>If you receive, then transmit</dt>
<dd>If your peer raises the radio state, you may as well use it.</dd>
<di><dt>Transmit no data.</dt>
<dd>Transmitting costs significant power, and moreover raises the radio state. Not transmitting will allow it to maximize the time spent in the low-cost Idle state.</dd></di>
<di><dt>If you must transmit, then transmit only a small volume.</dt>
<dd>If there is only a small amount of data transmitted - less than 128 octets typically - the radio will only raise to FACH, which is significantly cheaper than DCH.</dd></di>
<di><dt>If you must transmit, then compress as hard as possible.</dt>
<dd>Since individual octets have an associate power - and often financial - cost, it's worth maximizing the compression algorithm, even if the volume of traffic will raise to DCH.</dd></di>
<di><dt>If you have transmit a lot, then do a lot</dt>
<dd>If the radio is raised to DCH anyway, then you may as well go fetch that avatar you were missing, since you're chewing through power anyway.</dd></di>
<di><dt>If you receive, then transmit</dt>
<dd>If your peer raises the radio state, you may as well use it.</dd></di>
</dl>
<p>And for servers, similar rules apply:</p>
<dl>
<dt>Send no data.</dt>
<dd>Sending data will cause the handset to be raised out of Idle. This immediately costs massively higher power.</dd>
<dt>If you must send, send tiny bits.</dt>
<dd>Sending small enough data maximizes the likelyhood that the devices radio will only be raised to FACH levels.</dd>
<dt>If you receive, then send anything you have.</dt>
<dd>Receiving data indicates that the radio is active - it'll stay active for some time, so sending data doesn't incur the overhead of raising the radio state, and won't increase power drain on the handset.</dd>
<dt>If you must send when not receiving, send plenty.</dt>
<dd>Sending data will raise the radio's state - unless you can tell this will only raise it to FACH, it's worth sending as much as possible.</dd>
<di><dt>Send no data.</dt>
<dd>Sending data will cause the handset to be raised out of Idle. This immediately costs massively higher power.</dd></di>
<di><dt>If you must send, send tiny bits.</dt>
<dd>Sending small enough data maximizes the likelyhood that the devices radio will only be raised to FACH levels.</dd></di>
<di><dt>If you receive, then send anything you have.</dt>
<dd>Receiving data indicates that the radio is active - it'll stay active for some time, so sending data doesn't incur the overhead of raising the radio state, and won't increase power drain on the handset.</dd></di>
<di><dt>If you must send when not receiving, send plenty.</dt>
<dd>Sending data will raise the radio's state - unless you can tell this will only raise it to FACH, it's worth sending as much as possible.</dd></di>
</dl>
<p>Finally, protocol designers should aim to minimize any responses required from the handset, and ensure keepalive traffic, if any, fits inside FACH wherever possible.</p>
</section1>

View File

@ -2,6 +2,7 @@
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY MOVED "&lt;moved/&gt;">
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
@ -111,10 +112,10 @@
user@example.com.</p>
<dl>
<dt><strong>original JID</strong></dt>
<dd>user@example.com</dd>
<dt><strong>new JID</strong></dt>
<dd>user2@example2.com</dd>
<di><dt>original JID</dt>
<dd>user@example.com</dd></di>
<di><dt>new JID</dt>
<dd>user2@example2.com</dd></di>
</dl>
<section2 topic='Unsubscribing the original JID from outbound subscriptions'
@ -285,7 +286,7 @@
the user to subscribe to the new JID listed in the &MOVED; element.</p>
<p>Because of the ability to spoof the &MOVED; element, the client SHOULD
NOT automatically subscribe to the &MOVED; element target</p>.
NOT automatically subscribe to the &MOVED; element target.</p>
</section3>
<section3 topic='Roster state and action table' anchor='actions'>

View File

@ -531,13 +531,12 @@
<p>The client MAY include initial configuration and occupant list (the list MUST NOT include the creator). The server MAY allow sending incomplete configuration form. In such case the server MUST use default values for missing fields. The server MAY enforce a minimal occupant list length.</p>
<p>The service MAY either give the creator the 'owner' or 'member' status. In the latter case all users are equal.</p>
<p>Upon room creation success, the service MUST reply with an empty IQ result.</p>
<p>The following rules (similar to the ones relevant to the affiliation change request) apply to the occupant list:
<ul>
<li>'none' affiliation cannot be used.</li>
<li>All user bare JIDs must be unique</li>
<li>At most one owner can be chosen. In such case the room creator will become "just" a 'member'.</li>
</ul>
</p>
<p>The following rules (similar to the ones relevant to the affiliation change request) apply to the occupant list:</p>
<ul>
<li>'none' affiliation cannot be used.</li>
<li>All user bare JIDs must be unique</li>
<li>At most one owner can be chosen. In such case the room creator will become "just" a 'member'.</li>
</ul>
<p>After the room is created (but before receiving IQ result), new occupants (including creator) receive &MESSAGE; from the room with their affiliations (stanza MUST include only recipient's affiliation) and initial room version. &lt;prev-version /&gt; element MUST NOT be included.</p>
<example caption='Client requests room creation'><![CDATA[
<iq from='crone1@shakespeare.lit/desktop'
@ -770,7 +769,7 @@
<li>All changes must be meaningful, e.g. setting member's affiliation to 'member' is considered a bad request.</li>
<li>Server MAY allow members to add new members but they still cannot make anyone an 'owner' or remove other users from the room.</li>
</ol>
<p>On success the server will reply with result IQ with all changed items. <b>BEFORE</b> returning the IQ result, the service MUST route a message with affiliation change to all relevant users.</p>
<p>On success the server will reply with result IQ with all changed items. <strong>BEFORE</strong> returning the IQ result, the service MUST route a message with affiliation change to all relevant users.</p>
<p>Newcomers, i.e. users that were not occupants before the change, SHOULD receive only their own affiliation and SHOULD NOT receive &lt;prev-version /&gt; element.</p>
<p>The notifications must include both the new and old room version (&lt;version /&gt; and &lt;prev-version /&gt; respectively) string (except for the ones directed to users that have been removed from the room).</p>
<p>The notifications contain a list of items. The item list may be different from the list in IQ set, because some of the changes may require additional operations, e.g. choosing new owner when the old one leaves. Users, that are still in the room after change, will receive full change list. Users, that have been removed from the room with the request, will get only one item: themselves with affiliation 'none'.</p>
@ -1007,13 +1006,12 @@
</section2>
<section2 topic='Request sender has insufficient privileges' anchor='insufficient-privileges'>
<p>If the request sender does not have sufficient privileges (but is a room occupant), the service MUST reply with a 'not-allowed' error.</p>
<p>It occurs in the following cases:
<ul>
<li>A member tries to change the configuration but the service is not configured to allow it. It does not apply to the subject change, although it has to be performed by sending &MESSAGE; with &SUBJECT;, not configuration &IQ;.</li>
<li>A member tries to change anyone's affiliation to 'none' or 'owner'.</li>
<li>A member tries to change someone's affiliation to 'member' but the service is not configured to allow it.</li>
</ul>
</p>
<p>It occurs in the following cases:</p>
<ul>
<li>A member tries to change the configuration but the service is not configured to allow it. It does not apply to the subject change, although it has to be performed by sending &MESSAGE; with &SUBJECT;, not configuration &IQ;.</li>
<li>A member tries to change anyone's affiliation to 'none' or 'owner'.</li>
<li>A member tries to change someone's affiliation to 'member' but the service is not configured to allow it.</li>
</ul>
<example caption='Prohibited IQ'><![CDATA[
<iq from='minion@shakespeare.lit/desktop'
id='privileges1'
@ -1483,17 +1481,15 @@
<section2 topic='Service limits and configuration' anchor='limits-and-config'>
<p>MUC Light service may be abused by malicious users, e.g. due to replicating single message for every room occupant. The list below contains suggested configurable limits that SHOULD be implemented.</p>
<p>The service features that might vary depending on specific application are included as well.</p>
<p>
<ul>
<li>Maximal count of rooms the user occupies.</li>
<li>Blocking feature enabled/disabled.</li>
<li>XEP-0045 compatibility mode enabled/disabled.</li>
<li>Room creator's initial affiliation: owner/member.</li>
<li>Room configuration may be changed by owner/occupants.</li>
<li>New members can be invited by owner/occupants.</li>
<li>Maximal room size.</li>
</ul>
</p>
<ul>
<li>Maximal count of rooms the user occupies.</li>
<li>Blocking feature enabled/disabled.</li>
<li>XEP-0045 compatibility mode enabled/disabled.</li>
<li>Room creator's initial affiliation: owner/member.</li>
<li>Room configuration may be changed by owner/occupants.</li>
<li>New members can be invited by owner/occupants.</li>
<li>Maximal room size.</li>
</ul>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>

View File

@ -49,25 +49,25 @@
</header>
<section1 topic='Introduction' anchor='intro'>
Jingle <cite>XEP-0166</cite> is used to negotiate peer to peer media sessions.
<p>Jingle <cite>XEP-0166</cite> is used to negotiate peer to peer media sessions.
Muji is a way to coordinate Jingle sessions between a group of people.
Muji conferences are held in <cite>XEP-0045</cite> rooms.
Muji conferences are held in <cite>XEP-0045</cite> rooms.</p>
</section1>
<section1 topic="How it works" anchor="howitworks">
A Muji conference has a number of contents, each of which has unique name.
<p>A Muji conference has a number of contents, each of which has unique name.
content type, and an encoding. Each participant may provide a stream for each
content, and communicates which contents they are willing to provide streams
for, along with encoding information, in their MUC presence. This serves two
purposes. Firstly, so that each participant knows which contents every other
participant provides. Secondly, so that there is a global payload type (PT)
mapping for the various contents, so that clients only need to encode and
payload each content that they provide once.
payload each content that they provide once.</p>
Participants are not required to participate all the contents that are
<p>Participants are not required to participate all the contents that are
available. For example, a Muji client might choose to only request audio
streams.
streams.</p>
</section1>
<section1 topic='Joining a conference' anchor='joining'>
@ -75,7 +75,7 @@ streams.
Joining a conference is done in two stages. The first step is to
declare that preparations are being done to either join or start a muji
session inside the MUC. This is indicated by the client sending a presence
stanza to the MUC with a preparing element in muji section.
stanza to the MUC with a preparing element in muji section.</p>
<code><![CDATA[
<presence from='wiccarocks@shakespeare.lit/laptop'
@ -90,11 +90,11 @@ streams.
</presence>
]]></code>
The client MUST then wait until the MUC rebroadcasts its presence message,
<p>The client MUST then wait until the MUC rebroadcasts its presence message,
after which it MUST wait for all other participants that had a preparing
element in their presence to finish preparation. Afterwards it should finish
it's own preparation by updating its presence with the contents it wants to
take part in.
take part in.</p>
<code><![CDATA[
<presence from='wiccarocks@shakespeare.lit/laptop'
@ -118,11 +118,8 @@ streams.
</muji>
</presence>
]]></code>
</p>
<p>
When a client adds a payload ID to a content description, it MUST have the
<p>When a client adds a payload ID to a content description, it MUST have the
same codec name and receiving parameters as the corresponding entries in
other participants' payload maps for that content. For instance, if Alice
defines a payload type with ID 98, codec Speex and a a clock rate of 8000
@ -170,7 +167,7 @@ streams.
<p>
Adding a stream follows a process similar to the joining a conference. As a
first step an updated presence stanza MUST be send which contains a preparing
element as part of the Muji section.
element as part of the Muji section.</p>
<code><![CDATA[
<presence from='wiccarocks@shakespeare.lit/laptop'
@ -191,13 +188,13 @@ streams.
</presence>
]]></code>
The client MUST then wait until the MUC rebroadcasts its presence message,
<p>The client MUST then wait until the MUC rebroadcasts its presence message,
after which it MUST wait for all other participants that had a preparing
element in their presence to finish their changes.
element in their presence to finish their changes.</p>
Afterwards the client should add the new content to the muji section of its
<p>Afterwards the client should add the new content to the muji section of its
presence and add the content to all the jingle sessions it had with
participants it shared the content with.
participants it shared the content with.</p>
<code><![CDATA[
<presence from='wiccarocks@shakespeare.lit/laptop'
@ -221,7 +218,6 @@ streams.
</muji>
</presence>
]]></code>
</p>
</section1>
<section1 topic='Removing a content' anchor='removecontent'>

View File

@ -23,6 +23,7 @@
<header>
<title>Multi-User Gaming</title>
<abstract>This document defines an XMPP protocol extension for multi-user gaming.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
@ -74,7 +75,6 @@
<initials>tg</initials>
<remark><p>First draft.</p></remark>
</revision>
&LEGALNOTICE;
</header>
<section1 topic='Introduction' anchor='intro'>
<p>
@ -197,8 +197,8 @@
</section2>
<section2 topic='Dramatis Personae' anchor='terms-personae'>
Most of the examples in this document use the scenario of Miranda and Ferdinand playing chess in Act V, Scene I of Shakespeare's The Tempest,
represented here as the "island-chess@games.shakespeare.lit" room. The characters are as follows:
<p>Most of the examples in this document use the scenario of Miranda and Ferdinand playing chess in Act V, Scene I of Shakespeare's The Tempest,
represented here as the "island-chess@games.shakespeare.lit" room. The characters are as follows:</p>
<table caption='Dramatis Personae'>
<tr>
<th>Room Nickname</th><th>Full JID</th><th>Affiliation</th><th>Game Role</th>
@ -216,7 +216,7 @@
</section1>
<section1 topic='Affiliations' anchor='affiliations'>
The following affiliations are defined:
<p>The following affiliations are defined:</p>
<ol>
<li>Member</li>
<li>Owner</li>
@ -239,10 +239,10 @@
</p>
<section2 topic='Privileges' anchor='privileges'>
Owners are allowed to do what they like (saving/loading, change match options, etc.)
<p>Owners are allowed to do what they like (saving/loading, change match options, etc.)
except in unmoderated matches. This match type restricts the use of owner privileges to specific room statuses.
Users with no affiliation SHALL NOT enter members-only matches.
Besides that, these users have the same privileges as members.
Besides that, these users have the same privileges as members.</p>
<table caption='Owner Privileges Overview'>
<tr>
<th>Room Type</th>
@ -275,11 +275,11 @@
</section2>
<section2 topic='Changing Affiliations' anchor='changing-affi'>
The ways in which a user's affiliation changes are well-defined.
<p>The ways in which a user's affiliation changes are well-defined.
Sometimes the change results from the user's own action (e.g., registering as a member of the match),
whereas sometimes the change results from an action taken by an owner.
If a user's affiliation changes, a MUG service implementation MUST change the user's affiliation to reflect the change
and communicate that to all occupants.
and communicate that to all occupants.</p>
</section2>
</section1>
@ -762,10 +762,10 @@
<section1 topic="Occupant Use Cases" anchor='occupantusecases'>
<section2 topic='Invitation' anchor='mug-invite'>
It can be useful to invite other users to a room in which one is an occupant.
<p>It can be useful to invite other users to a room in which one is an occupant.
To do this, a MUG client sends XML of the following form to the &ROOM; itself
adding an &INVITE; element for every invitee.
(the reason is OPTIONAL and the message MUST be explicitly or implicitly of type "normal"):
(the reason is OPTIONAL and the message MUST be explicitly or implicitly of type "normal"):</p>
<example caption="Occupant Sends an Invitation by Way of Room"><![CDATA[
<message
from='ferdinand@shakespeare.lit/desktop'
@ -2039,7 +2039,7 @@
<p>
If the room creation fails because the specified room configuration options violate
one or more service policies (e.g., because the password for a password-protected room is blank),
the service MUST return a <not-acceptable/> error.
the service MUST return a &lt;not-acceptable/&gt; error.
</p>
<example caption='Service Informs Owner that Requested Configuration Options Are Unacceptable'><![CDATA[

View File

@ -94,7 +94,7 @@
</section2>
<section2 topic='Redirection' anchor='usecases-redirection'>
<p>A given deployment MAY wish to redirect users to another medium (e.g., a website) for further stages of registration, rather than allowing in-band registration. The recommended approach is to include only the <instructions/> element rather than the required fields or a data form in the IQ result, as well as a URL encoded using &xep0066;</p>
<p>A given deployment MAY wish to redirect users to another medium (e.g., a website) for further stages of registration, rather than allowing in-band registration. The recommended approach is to include only the &lt;instructions/&gt; element rather than the required fields or a data form in the IQ result, as well as a URL encoded using &xep0066;</p>
<example caption='Host Redirects Entity to Web Registration'><![CDATA[
<iq type='result'
from='sms.shakespeare.lit'

View File

@ -19,7 +19,6 @@
<supersedes/>
<supersededby/>
<shortname>inbox</shortname>
<schemaloc/>
<author>
<firstname>Valerian</firstname>
<surname>Saliou</surname>

View File

@ -13,8 +13,9 @@
<status>Experimental</status>
<type>Informational</type>
<sig>Standards</sig>
<supersedes>None</supersedes>
<supersededby>None</supersededby>
<dependencies/>
<supersedes/>
<supersededby/>
<shortname>namespace</shortname>
&dcridland;
&stpeter;

View File

@ -22,7 +22,7 @@
<spec>XEP-0114</spec>
<spec>XEP-0225</spec>
</supersedes>
<supersededby>None</supersededby>
<supersededby/>
<shortname>comp-s2s</shortname>
&dcridland;
<revision>

216
inbox/sasl2.xml Normal file
View File

@ -0,0 +1,216 @@
<?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>Extensible SASL Profile</title>
<abstract>This document describes a replacement for the SASL profile documented in RFC 6120 which allows for greater extensibility.</abstract>
&LEGALNOTICE;
<number>XXXX</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<dependencies>
<spec>XMPP Core</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>sasl2</shortname>
&dcridland;
<revision>
<version>0.0.1</version>
<date>2017-02-07</date>
<initials>dwd</initials>
<remark>
<ul>
<li>Initial Revision</li>
</ul>
</remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>While SASL provides an excellent framework that has served us well over the past 18 years, a number of shortcomings in the profile - the syntax binding to XMPP - that is in use.</p>
<p>This specification addresses a number of shortfalls:</p>
<ul>
<li>Number of round trips</li>
<li>Extensibility</li>
<li>Support for second factor</li>
<li>Support for mandatory password changes</li>
</ul>
<p>The new SASL profile documented herein is primarily a syntactic change to allow extensibility, combined with removal of the (largely) redundant stream restart, and additional results beyond total success or abject failure.</p>
<section2 topic="Terminology">
<p>Although initiating entities, in general, use SASL, and receiving entities offer it, the SASL specification and common parlance both use "Client " and "Server"; this specification uses Client and Server and assumes C2S links. This is not intended to preclude use of this SASL profile on S2S links. The term "SASL2" is used to mean the new SASL profile specified in this document; however the same RFC 4422 definition of SASL (and SASL profiles) applies.</p>
<p>Examples often use hypothetical SASL mechanisms and sub-extensions; this specification does not intend to make a position on any particular SASL mechanism, and the Mandatory To Implement mechanisms are unaffected.</p>
</section2>
</section1>
<section1 topic='Overview' anchor="overview">
<section2 topic="Discovering Support" anchor="feature">
<p>Servers capable of SASL2 offer a stream feature of &lt;mechanisms/>, qualified by the "urn:xmpp:sasl:0" namespace. This in turn contains one or more &lt;mechanism/> elements in the same namespace, and potentially other elements (for example, the &lt;hostname/> element defined within XEP-0233).</p>
<p>Note that SASL2 is impossible for clients to initiate without at least one mechanism being available, and therefore MUST NOT be offered.</p>
<p>The feature so advertised, and its child content, SHOULD be stable for the given stream to and from attributes and encryption state, and therefore MAY be cached by clients for later connections.</p>
<p>The Service Name used by XMPP is unchanged from RFC 6120.</p>
</section2>
<section2 topic="SASL Data Encoding">
<p>In all cases, both Clients and Servers encode SASL exchanges using Base 64 encoding. This SHOULD NOT include any line wrapping or other whitespace. As the form &lt;element/> is equivalent to &lt;element>&lt;/element>, these both indicate an empty string, which is used to indicate no data (ie, the absence of the data). In order to explicitly transmit a zero-length SASL challenge or response, the sending party sends a single equals sign character ("=").</p>
</section2>
<section2 topic="Initiation">
<p>Clients, upon observing this stream feature, initiate the authentication by the use of the &lt;authenticate/> top-level element, within the same namespace. The nature of this element is to inform the server about properties of the final stream state, as well as initiate authentication itself. To achieve the latter, it has a single mandatory attribute of "mechanism", with a string value of a mechanism name offered by the Server in the stream feature, and an optional child element of &lt;initial-response/>, containing a base64-encoded SASL Initial Response.</p>
<p>On subsequent connections, if a Client has previously cache the stream feature, the Client MAY choose to send it before seeing the stream features - sending it "pipelined" with the Stream Open tag for example.</p>
<example caption="An authentication request"><![CDATA[
<authenticate xmlns='urn:xmpp:sasl:0' mechanism="BLURDLYBLOOP">
<initial-response>SW1wcm92ZWQgZW5jYXNwdWxhdGlvbiBvZiBvcHRpb25hbCBTQVNMLUlSIGRhdGE=</initial-response>
</authenticate>
]]>
</example>
<p>In order to provide support for other desired stream states beyond authentication, additional child elements are used. For example, a hypothetical XEP-0198 session resumption element might be included, and/or Resource Binding requests.</p>
<example caption="An authentication request with a (hypothetical) bind request"><![CDATA[
<authenticate xmlns='urn:xmpp:sasl:0' mechanism='BLURDYBLOOP'>
<initial-response>
U0FTTC1JUiBlbmNvZGVkIGFsb25nc2lkZSBiaW5kIHJlcXVlc3Q=
</initial-response>
<bind xmlns='urn:xmpp:bind:example'/>
</authenticate>
]]>
</example>
</section2>
<section2 topic="Challenges and Responses" anchor="challenge">
<p>Server Challenges MAY then be sent. Each Challenge MUST be responded to by a Client in a Client Response. These are not extensible, and contain the corresponding base64 encoded SASL data:</p>
<example caption="A challenge and response exchange"><![CDATA[
<!-- A server might send: -->
<challenge xmlns='urn:xmpp:sasl:0'>
QmFzZSA2NCBlbmNvZGVkIFNBU0wgY2hhbGxlbmdlIGRhdGE=
</challenge>
<!-- A client might respond: -->
<response xmlns='urn:xmpp:sasl:0'>
QmFzZSA2NCBlbmNvZGVkIFNBU0wgcmVzcG9uc2UgZGF0YQ==
</response>
]]>
</example>
</section2>
<section2 topic="During Authentication">
<p>At any time while authentication is in progress, neither Client nor Server sends any element (including stanzas) or other data except the top-level elements defined herein. Clients MUST NOT send whitespace, and MUST send only &lt;response/> elements as appropriate or an &lt;abort/> element to immediately cause an error. Servers MUST disconnect Clients immediately if any other traffic is received. Servers are similarly REQUIRED to send no whitespace, and only the &lt;response/> and completion elements from the section below.</p>
</section2>
<section2 topic="Completing Authentication">
<p>Authentication may complete in one of three ways. It may complete successfully, in which case the client is authenticated. It may also fail, in which case the client is not authenticated and the stream and session state remain entirely unchanged.</p>
<p>Finally, it may have completed successfully, but further interaction is required - for example, a password change or second-factor authentication.</p>
<section3 topic="Success">
<p>If the Client is now authenticated, the Server sends a &lt;success/> element, which contains an OPTIONAL &lt;additional-data/> element containing SASL additional data. It also contains a &lt;authorization-identity/> element containing the negotiated identity - this is a bare JID, unless resource binding has occurred, in which case it is a full JID.</p>
<example caption="Successful authentication"><![CDATA[
<success xmlns='urn:xmpp:sasl:0'>
<success-data>
T3B0aW9uYWwgQmFzZSA2NCBlbmNvZGVkIFNBU0wgc3VjY2VzcyBkYXRh
</success-data>
<authorization-identifier>juliet@montague.example/Balcony/a987dsh9a87sdh</authorization-identifier>
</success>
]]></example>
<p>Other extension elements MAY also be contained by the &lt;success/> element.</p>
<example caption="Successful re-authentication and resumption"><![CDATA[
<success xmlns='urn:xmpp:sasl:0'>
<additional-data>
T3B0aW9uYWwgQmFzZSA2NCBlbmNvZGVkIFNBU0wgc3VjY2VzcyBkYXRh
</additional-data>
<authorization-identifier>juliet@montague.example/Balcony/a987dsh9a87sdh</authorization-identifier>
<sm:resumed xmlns='urn:xmpp:sm:3:example' h='345' previd='124'/>
</success>
]]></example>
<p>Any security layer negotiated SHALL take effect after the ">" octet of the closing tag (ie, immediately after "&lt;/success>").</p>
</section3>
<section3 topic="Failure">
<p>A &lt;failure/> element is used by the server to terminate the authentication attempt. It MAY contain application-specific error codes, and MAY contain a textual error. It MUST contain one of the SASL error codes from RFC 6120 Section 6.5.</p>
<example caption="Failure"><![CDATA[
<failure xmlns='urn:xmpp:sasl:0'>
<aborted xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
<optional-application-specific xmlns='urn:something:else'/>
<text>This is a terrible example.</text>
</failure>
]]></example>
</section3>
<section3 topic="Continue" anchor="continue">
<p>A &lt;continue/> element is used to indicate that while the SASL exchange was successful, it is insufficient to allow authentication at this time.</p>
<p>This can be used to indicate that the Client needs to perform a Second Factor Authentication ("2FA"), or is required to change password. These are conducted as additional SASL mechanisms. Such SASL mechanisms MUST NOT change the authorization identifier, or introduce any security layer. The authorization identifer transmitted during the subsequent &lt;success/>, and any security layer which comes into effect after the eventual &lt;success/>, therefore MUST be that of the first mechanism.</p>
<p>The element contains a &lt;mechanisms/> element, as defined above as a stream feature, containing suitable mechanisms. It MAY contain an &lt;additional-data/> element, as the &lt;success/> element does.</p>
<p>Finally, it MAY contain a &lt;text/> element, which can contain human-readable data explaining the nature of the step required.</p>
<example caption="Continue Required"><![CDATA[
<continue xmlns='urn:xmpp:sasl:0'>
<additional-data>
T3B0aW9uYWwgQmFzZSA2NCBlbmNvZGVkIFNBU0wgc3VjY2VzcyBkYXRh
</additional-data>
<mechanisms>
<mechanism>HOTP-EXAMPLE</mechanism>
<mechanism>TOTP-EXAMPLE</mechanism>
<mechanisms>
<text>This account requires 2FA</text>
</continue>
]]></example>
<p>Clients respond with a &lt;next-authenticate/> element, which has a single mandatory attribute of "mechanism", containing the selected mechanism name, and contains an OPTIONAL base64 encoded initial response.</p>
<example caption="Client Continues"><![CDATA[
<next-authenticate xmlns='urn:xmpp:sasl' mechanism='TOTP-EXAMPLE'>
MkZBIG9yIHBhc3N3b3JkIGNoYW5nZSBvciBzb21ldGhpbmc=
</next-authenticate>
]]></example>
</section3>
</section2>
</section1>
<section1 topic="SASL Profile Definition">
<p>This provides pointers and/or clarifications to the <link url="#overview"/> in the order and manner defined in RFC 4422, section 4.</p>
<section2 topic="Service Name">
<p>The service name SHALL be "xmpp", as defined by RFC 6120.</p>
</section2>
<section2 topic="Mechanism negotiation">
<p>Servers list mechanisms during stream features (See <link url="#features"/>) and within the &lt;continue/> element (See <link url="#continue"/>).</p>
<p>TODO: Neither this specification nor RFC 6120 allow clients access to the mechanism list after SASL negotiation...?</p>
</section2>
<section2 topic="Message Definitions">
<section3 topic="Initiation">
<p>Clients initiate using the &lt;authenticate/> top level element (See <link url="#auth"/>, and after any &lt;continue/> with the &lt;next-authenticate/> message (See <link url="#continue"/>).</p>
</section3>
<section3 topic="Server Challenges and Client Responses">
<p>See <link url="#challenge"/>.</p>
</section3>
<section3 topic="Outcome">
<p>See <link url="#outcome"/>.</p>
</section3>
</section2>
<section2 topic="Non-Empty Authorization Strings">
<p>If a Client specifies an authorization string which is non-empty, the identifier is normalized by treating it as a JID, and performing normalization as described in RFC 7622.</p>
</section2>
<section2 topic="Aborting">
<p>Clients MAY abort unilaterally by sending &lt;abort/> as specified in <link url="#abort"/>.</p>
<p>Servers MAY abort unliterally by sending &lt;failure/> with the &lt;aborted/> error code as defined in <link url="#failure"/>.</p>
</section2>
<section2 topic="Security Layer Effect">
<p>See <link url="#success"/>.</p>
</section2>
<section2 topic="Security Layer Order">
<p>Option (a) is used - any SASL Security Layer is applied first to data being sent, and TLS applied last.</p>
</section2>
<section2 topic="Multiple Authentication">
<p>Although the &lt;continue/> concept does use multiple SASL sequences, only the first SASL mechanism used is considered an authentication, and only the first can negotiate a security layer.</p>
<p>In particular, once &lt;success/> has been sent by the server, any further &lt;authenticate/> element MUST result in a stream error.</p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>Relative to the SASL profile documented in RFC 6120, this introduces more data unprotected by any security layer negotiated by SASL itself.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This XEP requires no interaction with &IANA;. </p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>None.</p>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>The author wishes to share any credit with many members of the community, including Lance Stout, Ralph Meijer, and Florian Schmaus.</p>
</section1>
</xep>

View File

@ -244,7 +244,7 @@ Thus, for the meta data, the node id would be UUID_meta and the data value node
</section2>
<section2 topic='Device Metadata' anchor='devicem'>
Adapter publishes device meta data:
<p>Adapter publishes device meta data:</p>
<code><![CDATA[
<iq type='set'
to='pubsub.capulet.lit'
@ -315,7 +315,6 @@ If the meta node is configured to include payloads, the subscribers will receive
</message>
]]></code>
<table caption='Device Attributes'>
<tbody>
<tr>
<th>
Attribute
@ -373,11 +372,9 @@ If the meta node is configured to include payloads, the subscribers will receive
A serial number or other unique identifier for the physical device
</td>
</tr>
</tbody>
</table>
<table caption='Transducer Attributes'>
<tbody>
<tr>
<th>
Attribute
@ -507,13 +504,11 @@ The tuple (UUID X, transducer id Y) MUST be unique such that a publish operation
The accuracy of the values reported by this transducer
</td>
</tr>
</tbody>
</table>
<section3 topic='Types' anchor='types'>
<p>To make it easier for agents to sort through available devices and seonsors, it is desirable for implementations to use a common set of types. The following device types are defined:
</p>
<table caption='Device Types'>
<tbody>
<tr>
<th>
Type
@ -610,7 +605,6 @@ The tuple (UUID X, transducer id Y) MUST be unique such that a publish operation
Other type that isn't listed above
</td>
</tr>
</tbody>
</table>
</section3>
<section3 topic='Units' anchor='units'>
@ -618,7 +612,7 @@ The tuple (UUID X, transducer id Y) MUST be unique such that a publish operation
SI conventions as shown in the <link url='http://aurora.regenstrief.org/~ucum/ucum.html'>The Unified Code For Units of Measurement</link>.
</p>
<p>
After specifying the units of the transducer device, you can then also specify an SI scalar value as powers of 10. The following example shows how to specify a sensor in centimeters.
After specifying the units of the transducer device, you can then also specify an SI scalar value as powers of 10. The following example shows how to specify a sensor in centimeters.</p>
<code><![CDATA[
<device id='01020301' type='other'>
<transducer name='inchworm movement' id='0001'
@ -626,7 +620,7 @@ After specifying the units of the transducer device, you can then also specify a
</device>
]]></code>
The following example shows how to specify a sensor in kilograms.
<p>The following example shows how to specify a sensor in kilograms.</p>
<code><![CDATA[
<device id='xyzzy' type='scale'>
<transducer name='bathroom scale' id='0001'
@ -634,7 +628,7 @@ The following example shows how to specify a sensor in kilograms.
</device>
]]></code>
The following example shows how to specify a sensor in kilowatt-second with a resolution to the nearest 0.1 kWh.
<p>The following example shows how to specify a sensor in kilowatt-second with a resolution to the nearest 0.1 kWh.</p>
<code><![CDATA[
<device id='windmill087' type='resource generation'>
<transducer name='home wind generator' id='0001'
@ -644,12 +638,12 @@ The following example shows how to specify a sensor in kilowatt-second with a re
</device>
]]></code>
If no unitScaler value is specified, then a unitScaler of 0 (aka 10**0 = 1) is assumed.
<p>If no unitScaler value is specified, then a unitScaler of 0 (aka 10**0 = 1) is assumed.
</p>
</section3>
</section2>
<section2 topic='Transducer Values' anchor='transducervalues'>
Values for a transducer are published via the data value node:
<p>Values for a transducer are published via the data value node:</p>
<code><![CDATA[
<iq type='set'
to='pubsub.capulet.lit'
@ -700,7 +694,6 @@ If the data value node is configured to include payloads, the subscribers will r
</message>
]]></code>
<table caption='Transducer Value Attributes'>
<tbody>
<tr>
<th>
Attribute
@ -744,7 +737,6 @@ The tuple (UUID X, transducer id Y) MUST be unique such that a publish operation
The raw value as seen by the transducer. The rawValue can be used to record a non-unit converted value for record keeping (e.g. a raw ADC value before calibration).
</td>
</tr>
</tbody>
</table>
<p>OPTIONAL: Instead of putting all of the transducer values into a single data value node, an adapter MAY want to break up the transducer values into multiple nodes.
For example, an adapter may want to do this for reasons of security (allow some entities to subscribe/publish to transducer Y1 and a different set of entities to subscribe/publish to transducer Y2).
@ -804,7 +796,7 @@ The information in the meta node is used by consumers to determine which node th
</p>
</section2>
<section2 topic='Setting Transducer Values' anchor='transducerset'>
Values for a transducer can also be set by publishing to the data value node.
<p>Values for a transducer can also be set by publishing to the data value node.</p>
<code><![CDATA[
<iq type='set'
to='pubsub.capulet.lit'
@ -886,7 +878,6 @@ If the fan node is configured to include payloads, the subscribers will receive
</message>
]]></code>
<table caption='Transducer Set Attributes'>
<tbody>
<tr>
<th>
Attribute
@ -922,7 +913,6 @@ The tuple (UUID X, transducer id Y) MUST be unique such that a publish operation
If the adapter can verify that the raw value is an allowable value for the transducer, it SHOULD allow the raw value to take precedence over the typedValue if provided.
</td>
</tr>
</tbody>
</table>
<section3 topic='Actuation' anchor='actuation'>
<p> Actuation takes place as a split-phase operation with an action signal (publish) followed by a completion callback (subscribed message).
@ -1153,12 +1143,11 @@ Event Node ID: 4d4335b5-4134-11e0-9207-0800200c9a66_data
</iq>
]]></code>
<p>Two things to note:
<p>Two things to note:</p>
<ol>
<li>The tuple ('4d4335b5-4134-11e0-9207-0800200c9a66_data', 'tid1') uniquely identifies the motion sensor for this camera adapter.</li>
<li>It is not relevant to the subscriber of this node (the consumer of information) whether the camera has motion detection built in or whether the adapter is capturing images from the camera and using its own methodology for determining motion.</li>
</ol>
</p>
<p>
To continue this example further, let's assume an agent is subscribed to the data value node and can also publish to the tid2 node which controls the light.
In this case, an agent will receive notification that movement was sensed and can take action.
@ -1302,7 +1291,7 @@ If an adapter chooses to publish a subset of transducer data (for example, only
the changed values), it is possible for consumers who are off line or recently
activated to miss older values.
There are a variety of ways to handle this depending on the needs of the
implementor including (but not limited to):
implementor including (but not limited to):</p>
<ul>
<li>
Increase the history size of the node in the xmpp server so old entries can be obtained
@ -1317,7 +1306,7 @@ Put infrequent events in their own nodes and use data value node for frequent ev
Put frequent events in their own nodes and use data value node for infrequent events
</li>
</ul>
If an implementaion chooses to put some transducers values into their own nodes
<p>If an implementaion chooses to put some transducers values into their own nodes
(instead of putting them all into the data value node), remember that a transducer value MUST appear in either the data value node or its own node, but not both.
The meta node indicates to consumers which node they should subscribe to in order to be notified when new data is available for their chosen transducer.
</p>

View File

@ -162,10 +162,10 @@
<dl>
<di>
<dt>iq-sift</dt>
<dd>The server enables the client to sift all &IQ; stanzas or ones that match the specified criteria.</dd>
<dt>message-sift</dt>
<dd>The server enables the client to sift all &MESSAGE; stanzas or ones that match the specified criteria.</dd>
<dt>presence-sift</dt>
<dd>The server enables the client to sift all &IQ; stanzas or ones that match the specified criteria.</dd></di>
<di><dt>message-sift</dt>
<dd>The server enables the client to sift all &MESSAGE; stanzas or ones that match the specified criteria.</dd></di>
<di><dt>presence-sift</dt>
<dd>The server enables the client to sift all &PRESENCE; stanzas or ones that match the specified criteria.</dd>
</di>
</dl>
@ -175,14 +175,14 @@
<dl>
<di>
<dt>all</dt>
<dd>The server shall sift this kind of stanza no matter who the sender is. This is the <strong>default</strong>.</dd>
<dt>local</dt>
<dd>The server shall sift this kind of stanza only from entities associated with the same local domain as the user itself (not from remote domains).</dd>
<dt>others</dt>
<dd>The server shall sift this kind of stanza only from other entities (not from the user itself).</dd>
<dt>remote</dt>
<dd>The server shall sift this kind of stanza only from entities associated with remote domains (not from the same local domain as the user itself).</dd>
<dt>self</dt>
<dd>The server shall sift this kind of stanza no matter who the sender is. This is the <strong>default</strong>.</dd></di>
<di><dt>local</dt>
<dd>The server shall sift this kind of stanza only from entities associated with the same local domain as the user itself (not from remote domains).</dd></di>
<di><dt>others</dt>
<dd>The server shall sift this kind of stanza only from other entities (not from the user itself).</dd></di>
<di><dt>remote</dt>
<dd>The server shall sift this kind of stanza only from entities associated with remote domains (not from the same local domain as the user itself).</dd></di>
<di><dt>self</dt>
<dd>The server shall sift this kind of stanza only from the user itself (not from other entities).</dd>
</di>
</dl>
@ -193,10 +193,10 @@
<dl>
<di>
<dt>all</dt>
<dd>The server shall sift this kind of stanza if the recipient is the bare JID &LOCALBARE; of the user or the full JID &LOCALFULL; of the particular resource. This is the <strong>default</strong>.</dd>
<dt>bare</dt>
<dd>The server shall sift this kind of stanza only if the recipient is the bare JID &LOCALBARE; of the user.</dd>
<dt>full</dt>
<dd>The server shall sift this kind of stanza if the recipient is the bare JID &LOCALBARE; of the user or the full JID &LOCALFULL; of the particular resource. This is the <strong>default</strong>.</dd></di>
<di><dt>bare</dt>
<dd>The server shall sift this kind of stanza only if the recipient is the bare JID &LOCALBARE; of the user.</dd></di>
<di><dt>full</dt>
<dd>The server shall sift this kind of stanza only if the recipient is the full JID &LOCALFULL; of the particular resource.</dd>
</di>
</dl>

View File

@ -43,14 +43,14 @@
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>There are various spim protection methods exist in XMPP: &xep0016;, &xep0158;, &xep0191;, &xep0268; and &xep0275;. But they may not be sufficient enough:
<p>There are various spim protection methods exist in XMPP: &xep0016;, &xep0158;, &xep0191;, &xep0268; and &xep0275;. But they may not be sufficient enough:</p>
<ul>
<li>&xep0016; and &xep0191; define blocking mechanism only which is not always appropriate.</li>
<li>&xep0158; interacts badly with automated software such as gateways.</li>
<li>&xep0268; implies trusted network of servers.</li>
<li>&xep0275; concentrates on ranking only.</li>
</ul>
Service administrators might want to deploy server-based spim recognition software to fill in the gaps. However, every automated spim recognition suffers from <em>false positives</em> - situations where a stanza incorrectly qualified as spim. To avoid them, a spim filter doesn't block suspicious stanza, but marks it and sends to a client in a regular manner. A client software doesn't need to interrupt a user when processing such marked stanzas: for example, it may put them silently in "SPAM" folder, so a user can look through them at any time later. Furthermore, a spim filter may take user's experience into account. When a user receives an unsolicited stanza, he or she can mark it as spim. In this case a client software sends an automatic complaint to a server-based spim filter. This specification deals with both cases. Thus, in contrast to &xep0159;, it doesn't introduce any spim blocking techniques. Also, the various spim recognition procedures that may be employed by the server are beyond the scope of this document.
<p>Service administrators might want to deploy server-based spim recognition software to fill in the gaps. However, every automated spim recognition suffers from <em>false positives</em> - situations where a stanza incorrectly qualified as spim. To avoid them, a spim filter doesn't block suspicious stanza, but marks it and sends to a client in a regular manner. A client software doesn't need to interrupt a user when processing such marked stanzas: for example, it may put them silently in "SPAM" folder, so a user can look through them at any time later. Furthermore, a spim filter may take user's experience into account. When a user receives an unsolicited stanza, he or she can mark it as spim. In this case a client software sends an automatic complaint to a server-based spim filter. This specification deals with both cases. Thus, in contrast to &xep0159;, it doesn't introduce any spim blocking techniques. Also, the various spim recognition procedures that may be employed by the server are beyond the scope of this document.
</p>
</section1>
<section1 topic='Requirements' anchor='reqs'>
@ -143,13 +143,12 @@
</section1>
<section1 topic='Business Rules' anchor='rules'>
<p>A filtering entity SHOULD only add &lt;mark/&gt; or &lt;report/&gt; elements and a receiving entity SHOULD only process those elements if the corresponding stanza envolves an interaction with a human user: subscription requests, messages, conference invites, voice calls, etc. For example, it doesn't make a lot of sense to mark &xep0232; stanzas.</p>
<p>To avoid obvious false positives and user confusions, a filtering entity SHOULD NOT add &lt;mark/&gt; or &lt;report/&gt; elements to a stanza and a receiving entity SHOULD ignore &lt;mark/&gt; and &lt;report/&gt; elements of a stanza if:
<p>To avoid obvious false positives and user confusions, a filtering entity SHOULD NOT add &lt;mark/&gt; or &lt;report/&gt; elements to a stanza and a receiving entity SHOULD ignore &lt;mark/&gt; and &lt;report/&gt; elements of a stanza if:</p>
<ul>
<li>The receiving entity has the sender's subscription information of the type "both", "from" or "to".</li>
<li>The receiving entity has pending subscription to the sender, i.e. subscription of type "none" and ask='subscribe'.</li>
<li>The receiving entity has sent direct presence to the sender.</li>
</ul>
</p>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>If an entity supports the spim markers, it MUST report that by including a service discovery feature of "urn:xmpp:spim-marker:0" in response to a &xep0030; information request. If an entity supports the spim reports, it MUST report that by including a service discovery feature of "urn:xmpp:spim-report:0" in response to a &xep0030; information request:</p>

View File

@ -12,6 +12,7 @@
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
@ -1041,4 +1042,3 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
</section1>
</xep>

View File

@ -18,6 +18,7 @@
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
@ -263,29 +264,29 @@
<p>
During the game, players change in turn, each of them MUST send only one move at a time.
It MUST possess these attributes:
<table caption='&MOVE; attributes'>
<tr>
<td><strong>Name</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>'id'</td>
<td>REQUIRED</td>
<td>The number of the move. First move is 1.</td>
</tr>
<tr>
<td>'row'</td>
<td>REQUIRED</td>
<td>The horizontal position of the mark.</td>
</tr>
<tr>
<td>'col'</td>
<td>REQUIRED</td>
<td>The vertical position of the mark.</td>
</tr>
</table>
</p>
<table caption='&MOVE; attributes'>
<tr>
<td><strong>Name</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>'id'</td>
<td>REQUIRED</td>
<td>The number of the move. First move is 1.</td>
</tr>
<tr>
<td>'row'</td>
<td>REQUIRED</td>
<td>The horizontal position of the mark.</td>
</tr>
<tr>
<td>'col'</td>
<td>REQUIRED</td>
<td>The vertical position of the mark.</td>
</tr>
</table>
<example caption='Juliet Sends a Move'><![CDATA[
<message
to='tictactoe@games.shakespeare.lit'

View File

@ -18,6 +18,7 @@
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
@ -133,29 +134,29 @@
Furthermore, the &MESSAGE; stanza contains a &TURN; element which in turn contains exactly one &MOVE; element
qualified by 'http://jabber.org/protocol/games/tictactoe'.
It MUST possess these attributes:
<table caption='&MOVE; attributes'>
<tr>
<td><strong>Name</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>'id'</td>
<td>REQUIRED</td>
<td>The number of the move. First move is 1.</td>
</tr>
<tr>
<td>'row'</td>
<td>REQUIRED</td>
<td>The horizontal position of the mark.</td>
</tr>
<tr>
<td>'col'</td>
<td>REQUIRED</td>
<td>The vertical position of the mark.</td>
</tr>
</table>
</p>
<table caption='&MOVE; attributes'>
<tr>
<td><strong>Name</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>'id'</td>
<td>REQUIRED</td>
<td>The number of the move. First move is 1.</td>
</tr>
<tr>
<td>'row'</td>
<td>REQUIRED</td>
<td>The horizontal position of the mark.</td>
</tr>
<tr>
<td>'col'</td>
<td>REQUIRED</td>
<td>The vertical position of the mark.</td>
</tr>
</table>
<example caption='Part of the Match Between Romeo and Juliet'><![CDATA[
<message
from='romeo@montague.net/room'

View File

@ -121,7 +121,7 @@
device, they both MAY know the exact format and existence of supported
commands.
</p>
</section1>SkkdJi88C())oo
</section1>
<section1 topic='Glossary' anchor='glossary'>
<p>
@ -164,8 +164,8 @@
</p>
<p>
<em>Note: The text that follows assumes that implementors have
read and understood <cite>XEP-0050</cite>, password
generation algorithms described in &rfc4226; and <cite>RFC 6238</cite></em>,
read and understood &xep0050;, password
generation algorithms described in &rfc4226; and &rfc6238;</em>,
and randomness requirements described in &rfc4086;,
and know about one-time pads and perfect secrecy.
</p>
@ -173,8 +173,8 @@
<section2 topic='Authenticate with a Time-Based One-Time Password (TOTP)' anchor='set-totp'>
<p>
Time-Based One-Time Password (TOTP) algorithm described in
<cite>RFC 6238</cite> is an extension of the HMAC-based
One-Time Password (HOTP) algorithm defined in <cite>RFC 4226</cite>,
&rfc6238; is an extension of the HMAC-based
One-Time Password (HOTP) algorithm defined in &rfc4226;,
to support the time-based moving factor. In TOTP, time
reference and a time step replaces the counter in the HOTP
computation.
@ -431,14 +431,14 @@
</li>
</ul>
In each case, the Verifier MAY check Prover's JID right after
<p>In each case, the Verifier MAY check Prover's JID right after
receiving the first Ad-Hoc command or after a succesful verification
process.
process.</p>
If Prover's JID is not approved, the Verifier SHOULD
reply with &forbidden; error message.
<p>If Prover's JID is not approved, the Verifier SHOULD
reply with &forbidden; error message.</p>
After the a succesful verification the Verifier can, e.g.,
<p>After the a succesful verification the Verifier can, e.g.,</p>
<ul>
<li>start the wanted process,</li>
<li>ask access rights from additional provision servers,

View File

@ -55,7 +55,7 @@
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic='Retrieving rating' anchor='retrieverating'>
A user may obtain their own rating by sending an IQ-get with no to address and an element qualified by the rating namespace.
<p>A user may obtain their own rating by sending an IQ-get with no to address and an element qualified by the rating namespace.</p>
<example caption='Rating retrieval request'><![CDATA[
<iq from=romeo@montague.net
id=aa1a
@ -63,7 +63,7 @@
<query xmlns=rating />
</iq>
]]></example>
The server should return an IQ result stanza with <rating/> element:
<p>The server should return an IQ result stanza with &lt;rating/&gt; element:</p>
<example caption='Server Response'><![CDATA[
<iq type=result to=romeo@montague.net
id=aa1a
@ -74,8 +74,8 @@
</iq>
]]></example>
</section2>
<section3 topic='User-moderated server' anchor='usermodserver'>
In installations that run as chat servers, moderation of spam users can be delivered to online users and administrators. Users receiving spam from a bare JID can send an IQ stanza to the server that increases the user rating.
<section2 topic='User-moderated server' anchor='usermodserver'>
<p>In installations that run as chat servers, moderation of spam users can be delivered to online users and administrators. Users receiving spam from a bare JID can send an IQ stanza to the server that increases the user rating.</p>
<example caption='Reporting Spam/Abuse'><![CDATA[
<iq type=set
from=romeo@montague.net
@ -145,7 +145,7 @@
</p>
<p>
JIDs that are critical to server functionality or admins should have a
permanent <rating/> of -100 to indicate that they are protected. Should a
permanent &lt;rating/&gt; of -100 to indicate that they are protected. Should a
user attempt to report a protected user, the server should send the
following:
</p>
@ -178,7 +178,7 @@
XEP-0191 Blocking Command, or an internal implementation to prevent
communication from known spammer accounts.
</p>
</section3>
</section2>
</section1>
<section1 topic='Business Rules' anchor='rules'>
<p>OPTIONAL.</p>

1
inbox/xep.dtd Symbolic link
View File

@ -0,0 +1 @@
../xep.dtd

1
inbox/xep.ent Symbolic link
View File

@ -0,0 +1 @@
../xep.ent

View File

@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY rfc3920bis "<span class='ref'><link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>rfc3920bis</link></span> <note>RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core &lt;<link url='http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis'>http://tools.ietf.org/html/draft-ietf-saintandre-rfc3920bis</link>&gt;.</note>" >
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>

145
inxep.py
View File

@ -1,145 +0,0 @@
#!/usr/bin/env python
# File: inxep.py
# Version: 0.1
# Description: a script for announcing proto-XEPs
# Last Modified: 2004-09-14
# Author: Peter Saint-Andre (stpeter@jabber.org)
# License: public domain
# HowTo: ./inxep.py filename approver
# (note: do not include extension!)
## LICENSE ##
#
# Copyright (c) 1999 - 2010 XMPP Standards Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
## END LICENSE ##
# IMPORTS:
#
import glob
import os
from select import select
import smtplib
import socket
from string import split,strip,join,find
import sys
import time
from xml.dom.minidom import parse,parseString,Document
def getText(nodelist):
thisText = ""
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
thisText = thisText + node.data
return thisText
# READ in XEP filename (sans extension)
xepname = sys.argv[1];
if len(sys.argv) >= 3:
approver = sys.argv[2]
else:
approver = "XMPP Council"
xepfile = 'inbox/' + xepname + '.xml'
# PARSE XEP HEADERS:
#
# - title
# - abstract
# - version
# - date
# - initials
# - remark
thexep = parse(xepfile)
xepNode = (thexep.getElementsByTagName("xep")[0])
headerNode = (xepNode.getElementsByTagName("header")[0])
titleNode = (headerNode.getElementsByTagName("title")[0])
title = getText(titleNode.childNodes)
abstractNode = (headerNode.getElementsByTagName("abstract")[0])
abstract = getText(abstractNode.childNodes)
statusNode = (headerNode.getElementsByTagName("status")[0])
xepstatus = getText(statusNode.childNodes)
typeNode = (headerNode.getElementsByTagName("type")[0])
xeptype = getText(typeNode.childNodes)
revNode = (headerNode.getElementsByTagName("revision")[0])
versionNode = (revNode.getElementsByTagName("version")[0])
version = getText(versionNode.childNodes)
dateNode = (revNode.getElementsByTagName("date")[0])
date = getText(dateNode.childNodes)
initialsNode = (revNode.getElementsByTagName("initials")[0])
initials = getText(initialsNode.childNodes)
remarkNode = (revNode.getElementsByTagName("remark")[0])
remark = getText(remarkNode.childNodes)
# SEND MAIL:
#
# From: editor@xmpp.org
# To: standards@xmpp.org
# Subject: Proposed XMPP Extension: XEP-$xepnum ($title)
# Body:
# The XMPP Extensions Editor has received a proposal for a new XEP.
#
# Title: $title
#
# Abstract: $abstract
#
# URL: https://xmpp.org/extensions/inbox/$xepname.html
#
# The $approver will now consider whether to accept
# this proposal as a full XEP.
#
fromaddr = "editor@xmpp.org"
# for testing...
# toaddrs = "editor@jabber.org"
# for real...
toaddrs = "standards@xmpp.org"
thesubject = 'Proposed XMPP Extension: ' + title
introline = 'The XMPP Extensions Editor has received a proposal for a new XEP.'
titleline = 'Title: ' + title
abstractline = 'Abstract: ' + abstract
urlline = 'URL: https://xmpp.org/extensions/inbox/' + xepname + '.html'
actionline = 'The ' + approver + ' will decide in the next two weeks whether to accept this proposal as an official XEP.'
msg = "From: XMPP Extensions Editor <%s>\r\n" % fromaddr
msg = msg + "To: %s\r\n" % toaddrs
msg = msg + "Subject: %s\r\n" % thesubject
msg = msg + introline
msg = msg + "\r\n\n"
msg = msg + titleline
msg = msg + "\r\n\n"
msg = msg + abstractline
msg = msg + "\r\n\n"
msg = msg + urlline
msg = msg + "\r\n\n"
msg = msg + actionline
msg = msg + "\r\n\n"
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
# END

318
texml-xsl/cmp.xsl Normal file
View File

@ -0,0 +1,318 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
extension-element-prefixes="doc"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://xsltsl.org/xsl/documentation/1.0"
xmlns:str="http://xsltsl.org/string"
xmlns:cmp="http://xsltsl.org/cmp"
exclude-result-prefixes="cmp str doc"
>
<doc:reference xmlns="">
<referenceinfo>
<releaseinfo role="meta">
$Id$
</releaseinfo>
<author>
<surname>Hummel</surname>
<firstname>Mark</firstname>
</author>
<copyright>
<year>2003</year>
<holder>Mark Hummel</holder>
</copyright>
</referenceinfo>
<title>XML Compare</title>
<partintro>
<section>
<title>Introduction</title>
<para>This module provides a template for comparing two xml documents. </para>
</section>
</partintro>
</doc:reference>
<doc:template name="cmp:diff">
<refpurpose>Compare</refpurpose>
<refdescription>
<para>Compare two xml documents and display differences. Two xml documents are defined to be the same if: They have the matching elements and attributes, and that the data in the elements also match. The comparison is order sensitive. </para>
<para>The element names from the documents at the current depth are compared, followed by their values, then any attribute names and values are compared. The process is applied then to the subtrees of the documents.</para>
<para>Notes: If there are leaf nodes in one nodeset which don't exist in the other, the value of those 'extra' elements won't appear as a difference.
</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>ns1</term>
<term>ns2</term>
<listitem>
<para>The two nodesets which are to be compared. </para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the difference between the documents. </para>
<para>The format of the output is an xml document. A node is added to the result tree for every difference. The node contains the type of difference (e.g element name difference, attribute value difference, etc), the value in the first nodeset and the value in the second nodeset, and the parent node. The indentation level is the depth at which the difference was found relative to the first document. </para>
</refreturn>
</doc:template>
<!-- pass in a nodeset and compare. Is order sensitive. Output attribute, element and textual differences. -->
<xsl:template name="cmp:diff">
<xsl:param name="ns1"/>
<xsl:param name="ns2"/>
<!-- attribute compare -->
<!-- Optimisation attempt
Can probaby change this into one loop ie -
<xsl:for-each
i = position
if node1[i] = node2[i]...
-->
<!-- Need to check if there are two sets of attributes -->
<xsl:choose>
<xsl:when test='count($ns1/attribute::*) = count($ns2/attribute::*)'>
<xsl:for-each select="$ns1/attribute::*">
<xsl:variable name="name1" select="name()"/>
<xsl:variable name="value1" select="."/>
<xsl:variable name="i" select="position()"/>
<xsl:for-each select="$ns2/attribute::*">
<xsl:variable name="j" select="position()"/>
<xsl:variable name="name2" select="name()"/>
<xsl:variable name="value2" select="."/>
<xsl:if test="$i = $j">
<xsl:if test="$name1 != $name2">
<attributeNameDifference>
<parentElement><xsl:value-of select="name(..)"/></parentElement>
<before><xsl:value-of select="$name1"/></before>
<after><xsl:value-of select="$name2"/></after>
</attributeNameDifference>
</xsl:if>
<xsl:if test="$name1 = $name2 and $value1 != $value2">
<attributeValueDifference>
<parentElement><xsl:value-of select="name(..)"/></parentElement>
<before><xsl:value-of select="$value1"/></before>
<after><xsl:value-of select="$value2"/></after>
</attributeValueDifference>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<attributeNameDifference>
<parentElement>
<xsl:value-of select="name(..)"/>
</parentElement>
<before><xsl:value-of select='$ns1/attribute::*'/></before>
<after><xsl:value-of select='$ns2/attribute::*'/></after>
</attributeNameDifference>
</xsl:otherwise>
</xsl:choose>
<!-- Find element differences by comparing the element names from the same position in both documents. Iterate over all the nodes in the nodeset with the largest number of elements, so the extra elements will appear as differences. -->
<xsl:choose>
<!-- Define loop direction based on which tree has more nodes
FIXME: Replacing this with one for-each and a test for the case
of the second tree having more nodes would be more elegant
Solution: Add variable for direction and assign the 'larger' nodeset to that
variable. Then do one for-each.
FIXME: The solution is a bit too iterative. Make it more functional
-->
<xsl:when test="count($ns1) &gt; count($ns2)">
<xsl:for-each select="$ns1">
<xsl:variable name="i" select="position()"/>
<xsl:message>node[<xsl:value-of select='$i'/>]:
<xsl:value-of select='$ns1[$i]'/>
</xsl:message>
<!-- Element name compare -->
<xsl:if test="name($ns1[$i]) != name($ns2[$i])">
<elementNameDifference>
<parentElement><xsl:value-of select="name(..)"/></parentElement>
<before><xsl:value-of select="name($ns1[$i])"/></before>
<after><xsl:value-of select="name($ns2[$i])"/></after>
</elementNameDifference>
</xsl:if>
<!-- Element Value compare -->
<xsl:if test="count($ns1/*) = 0">
<xsl:if test="$ns1[$i] != $ns2[$i]">
<elementValueDifference>
<parentElement><xsl:value-of select="name(..)"/></parentElement>
<before><xsl:value-of select="$ns1[$i]"/></before>
<after><xsl:value-of select="$ns2[$i]"/></after>
</elementValueDifference>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$ns2">
<xsl:variable name="i" select="position()"/>
<!-- Element Name compare -->
<xsl:if test="name($ns1[$i]) != name($ns2[$i])">
<elementNameDifference>
<parentElement><xsl:value-of select="name(..)"/></parentElement>
<before><xsl:value-of select="name($ns1[$i])"/></before>
<after><xsl:value-of select="name($ns2[$i])"/></after>
</elementNameDifference>
</xsl:if>
<!-- value compare -->
<xsl:if test="count($ns2/*) = 0">
<xsl:if test="$ns2[$i] != $ns1[$i]">
<elementValueDifference>
<parentElement><xsl:value-of select="name(..)"/></parentElement>
<after><xsl:value-of select="$ns2[$i]"/></after>
<before><xsl:value-of select="$ns1[$i]"/></before>
</elementValueDifference>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
<!-- stop processing when leaf node is reached. -->
<xsl:if test="count($ns1/*) &gt; 0 and count($ns2/*) &gt; 0">
<xsl:call-template name="cmp:diff">
<xsl:with-param name="ns1" select="$ns1/*"/>
<xsl:with-param name="ns2" select="$ns2/*"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<!-- Return false if the two nodesets are not identical
-->
<xsl:template name="cmp:cmp">
<xsl:param name="ns1"/>
<xsl:param name="ns2"/>
<xsl:param name="depth"/>
<xsl:choose>
<xsl:when test='count($ns1) != count($ns2)'>
<xsl:value-of select='"countDiff"'/>
</xsl:when>
<xsl:when test='count($ns1/attribute::*) != count($ns2/attribute::*)'>
<xsl:value-of select='"countDiff"'/>
</xsl:when>
<xsl:when test='$ns1 and $ns2'>
<xsl:variable name='result'>
<xsl:call-template name='cmp:cmp'>
<xsl:with-param name='ns1' select='$ns1/*'/>
<xsl:with-param name='ns2' select='$ns2/*'/>
<xsl:with-param name='depth' select='$depth+1'/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test='$result = "countDiff"'>
<xsl:value-of select='$result'/>
</xsl:when>
<xsl:when test='$result = "textDiff"'>
<xsl:value-of select='$result'/>
</xsl:when>
<xsl:when test='$result = ""'>
<xsl:variable name='keyText1' select='name($ns1)'/>
<xsl:variable name='keyText2' select='name($ns2)'/>
<xsl:choose>
<!-- Check if the text of the nodesets are the same and the attributes-->
<xsl:when test='$ns1 = $ns2 and $keyText1 = $keyText2'>
<!-- Check the attribute names are the same -->
<!-- Number of attributes being different is caught higher up -->
<xsl:if test='count($ns1/attribute::*)'>
<xsl:for-each select='$ns1/attribute::*'>
<xsl:variable name='i' select='position()'/>
<xsl:variable name='name1' select='name(.)'/>
<xsl:variable name='value1' select='.'/>
<xsl:for-each select='$ns2/attribute::*'>
<xsl:variable name='j' select='position()'/>
<xsl:variable name='name2' select='name(.)'/>
<xsl:variable name='value2' select='.'/>
<xsl:if test='$i = $j and ($name1 != $name2 or
$value1 != $value2)'>
<xsl:value-of select='"textDiff"'/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<!--
<xsl:variable name='diffResult'>
<xsl:call-template name='cmp:diff'>
<xsl:with-param name='ns1' select='$ns1'/>
<xsl:with-param name='ns2' select='$ns2'/>
</xsl:call-template>
</xsl:variable>
<xsl:if test='not($diffResult = "")'>
<xsl:value-of select='"textDiff"'/>
</xsl:if>
-->
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='"textDiff"'/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:when test='$ns1 and not($ns2)'>
<xsl:value-of select='"structDiff"'/>
</xsl:when>
<xsl:when test='$ns2 and not($ns1)'>
<xsl:value-of select='"structDiff"'/>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

1447
texml-xsl/date-time.xsl Normal file

File diff suppressed because it is too large Load Diff

90
texml-xsl/example.xsl Normal file
View File

@ -0,0 +1,90 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
extension-element-prefixes="doc"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://xsltsl.org/xsl/documentation/1.0"
xmlns:eg="http://xsltsl.org/example"
>
<doc:reference xmlns="">
<referenceinfo>
<releaseinfo role="meta">
$Id$
</releaseinfo>
<author>
<surname>Ball</surname>
<firstname>Steve</firstname>
</author>
<copyright>
<year>2001</year>
<holder>Steve Ball</holder>
</copyright>
</referenceinfo>
<title>Example Stylesheet</title>
<partintro>
<section>
<title>Introduction</title>
<para>This module provides a template for adding stylesheet modules to the XSLT Standard Library.</para>
<para>To add a new module to the library, follow these easy steps:</para>
<orderedlist>
<listitem>
<para>Copy this file and replace its contents with the new module templates and documentation.</para>
</listitem>
<listitem>
<para>Copy the corresponding test file in the <filename>test</filename> directory. Replace its contents with tests for the new module.</para>
</listitem>
<listitem>
<para>Add an include element in the <filename>stdlib.xsl</filename> stylesheet.</para>
</listitem>
<listitem>
<para>Add an entry in the <filename>test/test.xml</filename> file.</para>
</listitem>
<listitem>
<para>Add entries in the <filename>test/test.xsl</filename> stylesheet.</para>
</listitem>
<listitem>
<para>Add an entry in the <filename>doc/build.xml</filename> file.</para>
</listitem>
</orderedlist>
<para>The <filename>example.xsl</filename> stylesheet provides a more extensive example.</para>
</section>
</partintro>
</doc:reference>
<doc:template name="eg:example" xmlns="">
<refpurpose>Template Example</refpurpose>
<refdescription>
<para>Provides a template for writing templates. Replace this paragraph with a description of your template</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>text</term>
<listitem>
<para>The example string</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns nothing.</para>
</refreturn>
</doc:template>
<xsl:template name="eg:example">
<xsl:param name="text"/>
</xsl:template>
</xsl:stylesheet>

789
texml-xsl/markup.xsl Normal file
View File

@ -0,0 +1,789 @@
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:doc='http://xsltsl.org/xsl/documentation/1.0'
xmlns:markup='http://xsltsl.org/markup'
xmlns:str='http://xsltsl.org/string'
extension-element-prefixes='doc markup str'>
<doc:reference xmlns=''>
<referenceinfo>
<releaseinfo role="meta">
$Id$
</releaseinfo>
<author>
<surname>Ball</surname>
<firstname>Steve</firstname>
</author>
<copyright>
<year>2003</year>
<year>2001</year>
<holder>Steve Ball</holder>
</copyright>
</referenceinfo>
<title>XML Markup Templates</title>
<partintro>
<section>
<title>Introduction</title>
<para>This stylesheet module provides functions for generating literal XML markup.</para>
</section>
</partintro>
</doc:reference>
<doc:template name="markup:xml-declaration" xmlns="">
<refpurpose>Create an XML Declaration</refpurpose>
<refdescription>
<para>This template returns an XML Declaration. Although the XSLT standard provides control over the generation of the XML Declaration, this template may be useful in circumstances where the values must be computed at runtime.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>version</term>
<listitem>
<para>Version number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>standalone</term>
<listitem>
<para>Standalone indication. Must be value "yes" or "no".</para>
</listitem>
</varlistentry>
<varlistentry>
<term>encoding</term>
<listitem>
<para>Character encoding.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an XML Declaration as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:xml-declaration'>
<xsl:param name='version' select="'1.0'"/>
<xsl:param name='standalone'/>
<xsl:param name='encoding'/>
<xsl:text disable-output-escaping='yes'>&lt;?xml version="</xsl:text>
<xsl:copy-of select="$version"/>
<xsl:text>"</xsl:text>
<xsl:choose>
<xsl:when test="string-length($standalone) = 0"/>
<xsl:when test='$standalone = "yes" or $standalone = "no"'>
<xsl:text> standalone="</xsl:text>
<xsl:copy-of select="$standalone"/>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">invalid value "<xsl:value-of select="$standalone"/>" for standalone attribute</xsl:message>
</xsl:otherwise>
</xsl:choose>
<xsl:if test='string-length($encoding) &gt; 0'>
<xsl:text> encoding="</xsl:text>
<xsl:copy-of select='$encoding'/>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:text disable-output-escaping='yes'>?&gt;
</xsl:text>
</xsl:template>
<doc:template name="markup:doctype-declaration" xmlns="">
<refpurpose>Create a Document Type Declaration</refpurpose>
<refdescription>
<para>This template returns a Document Type Declaration. Although the XSLT standard provides control over the generation of a Document Type Declaration, this template may be useful in circumstances where the values for the identifiers or the internal subset must be computed at runtime.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>docel</term>
<listitem>
<para>The name of the document element.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>publicid</term>
<listitem>
<para>The public identifier for the external DTD subset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>systemid</term>
<listitem>
<para>The system identifier for the external DTD subset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>internaldtd</term>
<listitem>
<para>The internal DTD subset.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns a Document Type Declaration as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:doctype-declaration'>
<xsl:param name='docel'/>
<xsl:param name='publicid'/>
<xsl:param name='systemid'/>
<xsl:param name='internaldtd'/>
<xsl:if test='string-length($docel) = 0'>
<xsl:message terminate='yes'>No document element specified</xsl:message>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE </xsl:text>
<xsl:copy-of select="$docel"/>
<xsl:call-template name='markup:external-identifier'>
<xsl:with-param name='publicid' select='$publicid'/>
<xsl:with-param name='systemid' select='$systemid'/>
<xsl:with-param name='leading-space' select='true()'/>
</xsl:call-template>
<xsl:if test='string-length($internaldtd) &gt; 0'>
<xsl:text> [</xsl:text>
<xsl:copy-of select='$internaldtd'/>
<xsl:text>]</xsl:text>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&gt;
</xsl:text>
</xsl:template>
<doc:template name="markup:element-declaration" xmlns="">
<refpurpose>Create an Element Declaration</refpurpose>
<refdescription>
<para>This template returns an element declaration..</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>type</term>
<listitem>
<para>The element type.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>content-spec</term>
<listitem>
<para>The content specification.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an element declaration as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:element-declaration'>
<xsl:param name='type'/>
<xsl:param name='content-spec' select="'ANY'"/>
<xsl:if test='string-length($type) = 0'>
<xsl:message terminate='yes'>element type must be specified</xsl:message>
</xsl:if>
<xsl:if test='string-length($content-spec) = 0'>
<xsl:message terminate='yes'>content specification must be specified</xsl:message>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&lt;!ELEMENT </xsl:text>
<xsl:copy-of select='$type'/>
<xsl:text> </xsl:text>
<xsl:copy-of select='$content-spec'/>
<xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
</xsl:template>
<doc:template name="markup:attlist-declaration" xmlns="">
<refpurpose>Create an Attribute List Declaration</refpurpose>
<refdescription>
<para>This template returns an attribute list declaration.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>type</term>
<listitem>
<para>The element type.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>attr-defns</term>
<listitem>
<para>Attribute definitions.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an attribute list declaration as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:attlist-declaration'>
<xsl:param name='type'/>
<xsl:param name='attr-defns'/>
<xsl:if test='string-length($type) = 0'>
<xsl:message terminate='yes'>element type must be specified</xsl:message>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&lt;!ATTLIST </xsl:text>
<xsl:copy-of select='$type'/>
<xsl:text> </xsl:text>
<xsl:copy-of select='$attr-defns'/>
<xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
</xsl:template>
<doc:template name="markup:attribute-definition" xmlns="">
<refpurpose>Create an Attribute Definition</refpurpose>
<refdescription>
<para>This template returns an attribute definition.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>name</term>
<listitem>
<para>The attribute name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>type</term>
<listitem>
<para>The attribute type.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>default</term>
<listitem>
<para>The attribute default.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an attribute definition as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:attribute-definition'>
<xsl:param name='name'/>
<xsl:param name='type'/>
<xsl:param name='default'/>
<xsl:if test='string-length($name) = 0'>
<xsl:message terminate='yes'>attribute name must be specified</xsl:message>
</xsl:if>
<xsl:if test='string-length($type) = 0'>
<xsl:message terminate='yes'>attribute type must be specified</xsl:message>
</xsl:if>
<xsl:if test='string-length($default) = 0'>
<xsl:message terminate='yes'>attribute default must be specified</xsl:message>
</xsl:if>
<xsl:text> </xsl:text>
<xsl:copy-of select='$name'/>
<xsl:text> </xsl:text>
<xsl:copy-of select='$type'/>
<xsl:text> </xsl:text>
<xsl:copy-of select='$default'/>
</xsl:template>
<doc:template name="markup:entity-declaration" xmlns="">
<refpurpose>Create an Entity Declaration</refpurpose>
<refdescription>
<para>This template returns an entity declaration.</para>
<para>If the 'text' parameter is given a value, then an internal entity is created. If either the 'publicid' or 'systemid' parameters are given a value then an external entity is created. It is an error for the 'text' parameter to have value as well as the 'publicid', 'systemid' or 'notation' parameters.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>name</term>
<listitem>
<para>The entity name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>parameter</term>
<listitem>
<para>Boolean value to determine whether a parameter entity is created. Default is 'false()'.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>text</term>
<listitem>
<para>The replacement text. Must be a string.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>nodes</term>
<listitem>
<para>The replacement text as a nodeset. The nodeset is formatted as XML using the as-xml template. If both text and nodes are specified then nodes takes precedence.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>publicid</term>
<listitem>
<para>The public identifier for an external entity.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>systemid</term>
<listitem>
<para>The system identifier for an external entity.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>notation</term>
<listitem>
<para>The notation for an external entity.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an entity declaration as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:entity-declaration'>
<xsl:param name='name'/>
<xsl:param name='parameter' select='false()'/>
<xsl:param name='text'/>
<xsl:param name='nodes'/>
<xsl:param name='publicid'/>
<xsl:param name='systemid'/>
<xsl:param name='notation'/>
<xsl:if test='string-length($name) = 0'>
<xsl:message terminate='yes'>entity name must be specified</xsl:message>
</xsl:if>
<xsl:if test='string-length($text) &gt; 0 and
(string-length($publicid) &gt; 0 or
string-length($systemid) &gt; 0 or
string-length($notation) &gt; 0)'>
<xsl:message terminate='yes'>both replacement text and external identifier specified</xsl:message>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&lt;!ENTITY </xsl:text>
<xsl:copy-of select='$name'/>
<xsl:text> </xsl:text>
<xsl:if test="$parameter">
<xsl:text>% </xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="$nodes">
<xsl:call-template name='markup:quote-value'>
<xsl:with-param name='value'>
<xsl:call-template name="markup:as-xml">
<xsl:with-param name="nodes" select="$nodes"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:when test='$text'>
<xsl:call-template name='markup:quote-value'>
<xsl:with-param name='value' select='$text'/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name='markup:external-identifier'>
<xsl:with-param name='publicid' select='$publicid'/>
<xsl:with-param name='systemid' select='$systemid'/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
<xsl:if test='$notation'>
<xsl:text> NDATA "</xsl:text>
<xsl:copy-of select='$notation'/>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
</xsl:template>
<doc:template name="markup:quote-value" xmlns="">
<refpurpose>Quote an Attribute Value</refpurpose>
<refdescription>
<para>This template returns a quoted value.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>value</term>
<listitem>
<para>The value to quote.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns a quote value as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:quote-value'>
<xsl:param name='value'/>
<xsl:variable name="quoted">
<xsl:call-template name='markup:quote-value-aux'>
<xsl:with-param name='value' select='$value'/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($value, '&lt;')">
<xsl:call-template name='str:subst'>
<xsl:with-param name='text' select='$quoted'/>
<xsl:with-param name='replace'>&lt;</xsl:with-param>
<xsl:with-param name='with'>
<xsl:text disable-output-escaping='yes'>&amp;lt;</xsl:text>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select='$quoted'/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name='markup:quote-value-aux'>
<xsl:param name='value'/>
<!-- Quoting hell! -->
<xsl:variable name="quot">&quot;</xsl:variable>
<xsl:variable name="apos">&apos;</xsl:variable>
<xsl:choose>
<xsl:when test='contains($value, $quot) and contains($value, $apos)'>
<xsl:text>"</xsl:text>
<xsl:call-template name='str:subst'>
<xsl:with-param name='text' select='$value'/>
<xsl:with-param name='replace'>"</xsl:with-param>
<xsl:with-param name='with'>
<xsl:text disable-output-escaping='yes'>&amp;quot;</xsl:text>
</xsl:with-param>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test='contains($value, $quot)'>
<xsl:text>'</xsl:text>
<xsl:value-of select='$value'/>
<xsl:text>'</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>"</xsl:text>
<xsl:value-of select='$value'/>
<xsl:text>"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<doc:template name="markup:external-identifier" xmlns="">
<refpurpose>Create an External Identifier</refpurpose>
<refdescription>
<para>This template returns an external identifier.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>publicid</term>
<listitem>
<para>The public identifier.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>systemid</term>
<listitem>
<para>The system identifier.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an external identifier as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:external-identifier'>
<xsl:param name='publicid'/>
<xsl:param name='systemid'/>
<xsl:param name='leading-space' select='false()'/>
<xsl:choose>
<xsl:when test='string-length($publicid) &gt; 0'>
<xsl:if test='$leading-space'>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:text disable-output-escaping='yes'>PUBLIC "</xsl:text>
<xsl:value-of select='$publicid' disable-output-escaping='yes'/>
<xsl:text disable-output-escaping='yes'>"</xsl:text>
<xsl:if test='string-length($systemid) &gt; 0'>
<xsl:text disable-output-escaping='yes'> "</xsl:text>
<xsl:value-of select='$systemid' disable-output-escaping='yes'/>
<xsl:text disable-output-escaping='yes'>"</xsl:text>
</xsl:if>
</xsl:when>
<xsl:when test="string-length($systemid) &gt; 0">
<xsl:if test='$leading-space'>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:text disable-output-escaping='yes'>SYSTEM "</xsl:text>
<xsl:value-of select='$systemid' disable-output-escaping='yes'/>
<xsl:text disable-output-escaping='yes'>"</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
<doc:template name="markup:entity-reference" xmlns="">
<refpurpose>Create an Entity Reference</refpurpose>
<refdescription>
<para>This template returns an entity reference.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>name</term>
<listitem>
<para>The name of the entity.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an entity reference as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:entity-reference'>
<xsl:param name='name'/>
<xsl:text disable-output-escaping='yes'>&amp;</xsl:text>
<xsl:value-of select='$name'/>
<xsl:text>;</xsl:text>
</xsl:template>
<doc:template name="markup:notation-declaration" xmlns="">
<refpurpose>Create a Notation Declaration</refpurpose>
<refdescription>
<para>This template returns a notation declaration.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>name</term>
<listitem>
<para>The notation name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>publicid</term>
<listitem>
<para>The public identifier for the notation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>systemid</term>
<listitem>
<para>The system identifier for the notation.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns a notation declaration as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:notation-declaration'>
<xsl:param name='name'/>
<xsl:param name='publicid'/>
<xsl:param name='systemid'/>
<xsl:if test='string-length($name) = 0'>
<xsl:message terminate='yes'>notation name must be specified</xsl:message>
</xsl:if>
<xsl:if test='string-length($publicid) = 0 and string-length($systemid) = 0'>
<xsl:message terminate='yes'>external identifier must be specified</xsl:message>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&lt;!NOTATION </xsl:text>
<xsl:copy-of select='$name'/>
<xsl:call-template name='markup:external-identifier'>
<xsl:with-param name='publicid' select='$publicid'/>
<xsl:with-param name='systemid' select='$systemid'/>
<xsl:with-param name='leading-space' select='true()'/>
</xsl:call-template>
<xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
</xsl:template>
<doc:template name="markup:cdata-section" xmlns="">
<refpurpose>Create a CDATA Section</refpurpose>
<refdescription>
<para>This template returns a CDATA Section. The XSLT specification provides a mechanism for instructing the XSL processor to output character data in a CDATA section for certain elements, but this template may be useful in those circumstances where not all instances of an element are to have their content placed in a CDATA section.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>text</term>
<listitem>
<para>The content of the CDATA section.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns a CDATA section as a string.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:cdata-section'>
<xsl:param name='text'/>
<xsl:if test="contains($text, ']]&gt;')">
<xsl:message terminate="yes">CDATA section contains "]]&gt;"</xsl:message>
</xsl:if>
<xsl:text disable-output-escaping='yes'>&lt;![CDATA[</xsl:text>
<xsl:copy-of select='$text'/>
<xsl:text disable-output-escaping='yes'>]]&gt;</xsl:text>
</xsl:template>
<doc:template name="markup:as-xml" xmlns="">
<refpurpose>Format Nodeset As XML Markup</refpurpose>
<refdescription>
<para>This template returns XML markup. Each node in the given nodeset is converted to its equivalent XML markup.</para>
<para>BUG: This version may not adequately handle XML Namespaces.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>nodes</term>
<listitem>
<para>Nodeset to format as XML.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns XML markup.</para>
</refreturn>
</doc:template>
<xsl:template name='markup:as-xml'>
<xsl:param name='nodes'/>
<xsl:if test="$nodes">
<xsl:choose>
<xsl:when test="$nodes[1]/self::*">
<xsl:text disable-output-escaping='yes'>&lt;</xsl:text>
<xsl:value-of select="name($nodes[1])"/>
<xsl:for-each select="$nodes[1]/@*">
<xsl:text> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>=</xsl:text>
<xsl:call-template name='markup:quote-value'>
<xsl:with-param name='value' select='.'/>
</xsl:call-template>
</xsl:for-each>
<xsl:choose>
<xsl:when test='$nodes[1]/node()'>
<xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
<xsl:call-template name='markup:as-xml'>
<xsl:with-param name='nodes' select='$nodes[1]/node()'/>
</xsl:call-template>
<xsl:text disable-output-escaping='yes'>&lt;/</xsl:text>
<xsl:value-of select="name($nodes[1])"/>
<xsl:text disable-output-escaping='yes'>&gt;</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text disable-output-escaping='yes'>/&gt;</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$nodes[1]/self::text()">
<xsl:value-of select="$nodes[1]"/>
</xsl:when>
<xsl:when test="$nodes[1]/self::comment()">
<xsl:text disable-output-escaping='yes'>&lt;!--</xsl:text>
<xsl:value-of select="$nodes[1]"/>
<xsl:text disable-output-escaping='yes'>--&gt;</xsl:text>
</xsl:when>
<xsl:when test="$nodes[1]/self::processing-instruction()">
<xsl:text disable-output-escaping='yes'>&lt;?</xsl:text>
<xsl:value-of select="name($nodes[1])"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$nodes[1]"/>
<xsl:text disable-output-escaping='yes'>?&gt;</xsl:text>
</xsl:when>
<xsl:when test="not($nodes[1]/parent::*)"/> <!-- root node -->
<xsl:when test="count($nodes[1] | $nodes[1]/../namespace::*) = count($nodes[1]/../namespace::*)"/> <!-- namespace node -->
<xsl:when test="count($nodes[1] | $nodes[1]/../@*) = count($nodes[1]/../@*)"/> <!-- attribute node -->
</xsl:choose>
<xsl:call-template name="markup:as-xml">
<xsl:with-param name="nodes" select="$nodes[position() &gt; 1]"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

618
texml-xsl/math.xsl Normal file
View File

@ -0,0 +1,618 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://xsltsl.org/xsl/documentation/1.0"
xmlns:math="http://xsltsl.org/math"
exclude-result-prefixes="doc math">
<doc:reference xmlns="">
<referenceinfo>
<releaseinfo role="meta">
$Id$
</releaseinfo>
<author>
<surname>Ball</surname>
<firstname>Steve</firstname>
</author>
<copyright>
<year>2004</year>
<year>2002</year>
<holder>Steve Ball</holder>
</copyright>
</referenceinfo>
<title>Math Module</title>
<partintro>
<section>
<title>Introduction</title>
<para>This module provides mathematical functions.</para>
</section>
</partintro>
</doc:reference>
<doc:template name="math:power" xmlns="">
<refpurpose>Power</refpurpose>
<refdescription>
<para>Raises a number to a power.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>base</term>
<listitem>
<para>The base number. Must be a number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>power</term>
<listitem>
<para>The power to raise the number to. Must be an integer.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns base multiplied by itself power times. If the base or power are not numbers or if the power is fractional then an empty string is returned.</para>
</refreturn>
</doc:template>
<xsl:template name="math:power">
<xsl:param name="base"/>
<xsl:param name="power"/>
<xsl:choose>
<xsl:when test='$power = "0" and $base = "0"'>
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test='$power = "0" and number($base)'>
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test='$power = "0" and not(number($base))'/>
<xsl:when test='$base = "0" and number($power)'>
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:when test='not(number($base)) or not(number($power))'/>
<xsl:when test='floor(number($power)) != number($power)'/>
<xsl:when test='number($power) &lt; 0'>
<xsl:variable name='x'>
<xsl:call-template name='math:power'>
<xsl:with-param name='base' select='$base'/>
<xsl:with-param name='power' select='-1 * $power'/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select='1 div $x'/>
</xsl:when>
<xsl:when test='number($power) = 1'>
<xsl:value-of select='$base'/>
</xsl:when>
<xsl:when test='number($power) &gt; 0'>
<xsl:variable name='x'>
<xsl:call-template name='math:power'>
<xsl:with-param name='base' select='$base'/>
<xsl:with-param name='power' select='$power - 1'/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select='$base * $x'/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<doc:template name="math:cvt-hex-decimal" xmlns="">
<refpurpose>Conversion</refpurpose>
<refdescription>
<para>Converts a hexidecimal value to a decimal value.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>value</term>
<listitem>
<para>The hexidecimal number. Must be a number in hexidecimal format.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the value as a decimal string. If the value is not a number then a NaN value is returned.</para>
</refreturn>
</doc:template>
<xsl:template name="math:cvt-hex-decimal">
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test='$value = ""'/>
<xsl:when test='string-length($value) = 1'>
<xsl:call-template name='math:cvt-hex-decimal-digit'>
<xsl:with-param name='digit' select='$value'/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name='first-digit'>
<xsl:call-template name='math:cvt-hex-decimal-digit'>
<xsl:with-param name='digit' select='substring($value, 1, 1)'/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name='remainder'>
<xsl:call-template name='math:cvt-hex-decimal'>
<xsl:with-param name='value' select='substring($value, 2)'/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select='$first-digit * 16 + $remainder'/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name='math:cvt-hex-decimal-digit'>
<xsl:param name='digit' select='0'/>
<xsl:choose>
<xsl:when test='$digit &lt;= 9'>
<xsl:value-of select='$digit'/>
</xsl:when>
<xsl:when test='$digit = "a" or $digit = "A"'>10</xsl:when>
<xsl:when test='$digit = "b" or $digit = "B"'>11</xsl:when>
<xsl:when test='$digit = "c" or $digit = "C"'>12</xsl:when>
<xsl:when test='$digit = "d" or $digit = "D"'>13</xsl:when>
<xsl:when test='$digit = "e" or $digit = "E"'>14</xsl:when>
<xsl:when test='$digit = "f" or $digit = "F"'>15</xsl:when>
</xsl:choose>
</xsl:template>
<doc:template name="math:ordinal" xmlns="">
<refpurpose>Ordinal number</refpurpose>
<refdescription>
<para>Gives the ordinal number of a given counting number. For example, 1 becomes "1st".</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>number</term>
<listitem>
<para>An integer number.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the number with an ordinal suffix.</para>
</refreturn>
</doc:template>
<xsl:template name="math:ordinal">
<xsl:param name="number"/>
<xsl:choose>
<xsl:when test='$number &lt; 0'/>
<xsl:otherwise>
<xsl:value-of select='$number'/>
<xsl:choose>
<xsl:when test='$number = 11 or $number = 12 or $number = 13'>th</xsl:when>
<xsl:when test='$number mod 10 = 1'>st</xsl:when>
<xsl:when test='$number mod 10 = 2'>nd</xsl:when>
<xsl:when test='$number mod 10 = 3'>rd</xsl:when>
<xsl:otherwise>th</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<doc:template name="math:ordinal-as-word" xmlns="">
<refpurpose>Returns an ordinal number</refpurpose>
<refdescription>
<para>This template returns the ordinal number for a given counting number as a word. For example "first" for 1.</para>
<para>Only handles numbers less than 10000000 (ten million).</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>number</term>
<listitem>
<para>The counting number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>conjunctive</term>
<listitem>
<para>Whether to add the word "and" to the result, for example "one hundred and first" rather than "one hundred first". Default is "yes".</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the ordinal number as a string.</para>
</refreturn>
</doc:template>
<xsl:template name="math:ordinal-as-word">
<xsl:param name="number" select="0"/>
<xsl:param name='conjunctive' select='"yes"'/>
<xsl:param name='preceding' select='0'/>
<xsl:choose>
<xsl:when test='$preceding = 1 and $number = 0'/>
<xsl:when test='$number = 0'>zeroth</xsl:when>
<xsl:when test="$number &lt; 1 or $number != floor($number)"/>
<xsl:when test='$number = 1'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>first</xsl:text>
</xsl:when>
<xsl:when test='$number = 2'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>second</xsl:text>
</xsl:when>
<xsl:when test='$number = 3'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>third</xsl:text>
</xsl:when>
<xsl:when test='$number = 4'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>fourth</xsl:text>
</xsl:when>
<xsl:when test='$number = 5'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>fifth</xsl:text>
</xsl:when>
<xsl:when test='$number = 6'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>sixth</xsl:text>
</xsl:when>
<xsl:when test='$number = 7'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>seventh</xsl:text>
</xsl:when>
<xsl:when test='$number = 8'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>eighth</xsl:text>
</xsl:when>
<xsl:when test='$number = 9'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>ninth</xsl:text>
</xsl:when>
<xsl:when test='$number = 10'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>tenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 11'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>eleventh</xsl:text>
</xsl:when>
<xsl:when test='$number = 12'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>twelveth</xsl:text>
</xsl:when>
<xsl:when test='$number = 13'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>thirteenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 14'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>fourteenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 15'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>fifteenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 16'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>sixteenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 17'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>seventeenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 18'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>eighteenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 19'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>nineteenth</xsl:text>
</xsl:when>
<xsl:when test='$number = 20'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>twentieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 30'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>thirtieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 40'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>fortieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 50'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>fiftieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 60'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>sixtieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 70'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>seventieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 80'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>eightieth</xsl:text>
</xsl:when>
<xsl:when test='$number = 90'>
<xsl:if test='$preceding = 1'> and </xsl:if>
<xsl:text>ninetieth</xsl:text>
</xsl:when>
<xsl:when test='$number mod 1000000 = 0'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000000)'/>
</xsl:call-template>
<xsl:text> millionth</xsl:text>
</xsl:when>
<xsl:when test='$number &lt; 1000000 and $number mod 1000 = 0'>
<xsl:if test='$preceding = 1 and $conjunctive'> and </xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000)'/>
</xsl:call-template>
<xsl:text> thousandth</xsl:text>
</xsl:when>
<xsl:when test='$number &lt; 1000 and $number mod 100 = 0'>
<xsl:if test='$preceding = 1 and $conjunctive'> and </xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 100)'/>
</xsl:call-template>
<xsl:text> hundredth</xsl:text>
</xsl:when>
<xsl:when test='$number &gt; 1000000'>
<xsl:if test='$preceding = 1'>
<xsl:text> </xsl:text>
<xsl:if test='$conjunctive'>and </xsl:if>
</xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000000) * 1000000'/>
</xsl:call-template>
<xsl:choose>
<xsl:when
test='(floor(floor(($number mod 1000000) + 0.1) div 100000) > 0 and $number mod 100000 > 0) or
(floor(floor(($number mod 100000) + 0.1) div 10000) > 0 and $number mod 10000 > 0) or
(floor(floor(($number mod 10000) + 0.1) div 1000) > 0 and $number mod 1000 > 0) or
(floor(floor(($number mod 1000) + 0.1) div 100) > 0 and $number mod 100 > 0) or
(floor(floor(($number mod 100) + 0.1) div 10) > 0 and $number mod 10 > 0 and $number mod 100 > 20)'>
<xsl:text> </xsl:text>
<xsl:call-template name='math:ordinal-as-word'>
<xsl:with-param name='number' select='floor(($number mod 1000000) + 0.1)'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
<xsl:with-param name='preceding' select='0'/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name='math:ordinal-as-word'>
<xsl:with-param name='number' select='floor(($number mod 1000000) + 0.1)'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
<xsl:with-param name='preceding' select='1'/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test='$number &gt; 1000'>
<xsl:if test='$preceding = 1'>
<xsl:text> </xsl:text>
<xsl:if test='$conjunctive'>and </xsl:if>
</xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000) * 1000'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
</xsl:call-template>
<xsl:choose>
<xsl:when test='floor(floor(($number mod 1000) + 0.1) div 100) > 0'>
<xsl:text> </xsl:text>
<xsl:call-template name='math:ordinal-as-word'>
<xsl:with-param name='number' select='floor(($number mod 1000) + 0.1)'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
<xsl:with-param name='preceding' select='0'/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name='math:ordinal-as-word'>
<xsl:with-param name='number' select='floor(($number mod 1000) + 0.1)'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
<xsl:with-param name='preceding' select='1'/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test='$number &gt; 100'>
<xsl:if test='$preceding = 1'>
<xsl:text> </xsl:text>
<xsl:if test='$conjunctive'>and </xsl:if>
</xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 100) * 100'/>
</xsl:call-template>
<xsl:call-template name='math:ordinal-as-word'>
<xsl:with-param name='number' select='floor(($number mod 100) + 0.1)'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
<xsl:with-param name='preceding' select='1'/>
</xsl:call-template>
</xsl:when>
<xsl:when test='$number &gt; 20'>
<xsl:if test='$preceding = 1'>
<xsl:text> </xsl:text>
<xsl:if test='$conjunctive'>and </xsl:if>
</xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 10) * 10'/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:call-template name='math:ordinal-as-word'>
<xsl:with-param name='number' select='floor(($number mod 10) + 0.1)'/>
<xsl:with-param name='conjunctive' select='$conjunctive'/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<doc:template name="math:number-as-word" xmlns="">
<refpurpose>Returns a number as a word</refpurpose>
<refdescription>
<para>This template returns the word for a given integer number, for example "one" for 1.</para>
<para>Only handles numbers less than 10000000 (ten million).</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>number</term>
<listitem>
<para>The counting number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>conjunctive</term>
<listitem>
<para>Adds the word "and" where appropriate, for example.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the number as a string.</para>
</refreturn>
</doc:template>
<xsl:template name="math:number-as-word">
<xsl:param name="number" select="0"/>
<xsl:param name='conjunctive' select='true()'/>
<xsl:choose>
<xsl:when test='$number = 0'>zero</xsl:when>
<xsl:when test='$number &lt; 0'>
<xsl:text>minus </xsl:text>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='-1 * $number'/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$number != floor($number)"/>
<xsl:when test='$number mod 1000000 = 0'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000000)'/>
</xsl:call-template>
<xsl:text> million</xsl:text>
</xsl:when>
<xsl:when test='$number &gt;= 1000000'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000000)'/>
</xsl:call-template>
<xsl:text> million </xsl:text>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor(($number mod 1000000) + 0.1)'/>
</xsl:call-template>
</xsl:when>
<xsl:when test='$number mod 1000 = 0'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000)'/>
</xsl:call-template>
<xsl:text> thousand</xsl:text>
</xsl:when>
<xsl:when test='$number &gt;= 1000'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 1000)'/>
</xsl:call-template>
<xsl:text> thousand </xsl:text>
<xsl:if test='$conjunctive and floor(floor(($number mod 1000) + 0.1) div 100) = 0'>and </xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor(($number mod 1000) + 0.1)'/>
</xsl:call-template>
</xsl:when>
<xsl:when test='$number mod 100 = 0'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 100)'/>
</xsl:call-template>
<xsl:text> hundred</xsl:text>
</xsl:when>
<xsl:when test='$number &gt;= 100'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 100)'/>
</xsl:call-template>
<xsl:text> hundred </xsl:text>
<xsl:if test='$conjunctive'>and </xsl:if>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor(($number mod 100) + 0.1)'/>
</xsl:call-template>
</xsl:when>
<xsl:when test='$number = 1'>one</xsl:when>
<xsl:when test='$number = 2'>two</xsl:when>
<xsl:when test='$number = 3'>three</xsl:when>
<xsl:when test='$number = 4'>four</xsl:when>
<xsl:when test='$number = 5'>five</xsl:when>
<xsl:when test='$number = 6'>six</xsl:when>
<xsl:when test='$number = 7'>seven</xsl:when>
<xsl:when test='$number = 8'>eight</xsl:when>
<xsl:when test='$number = 9'>nine</xsl:when>
<xsl:when test='$number = 10'>ten</xsl:when>
<xsl:when test='$number = 11'>eleven</xsl:when>
<xsl:when test='$number = 12'>twelve</xsl:when>
<xsl:when test='$number = 13'>thirteen</xsl:when>
<xsl:when test='$number = 14'>fourteen</xsl:when>
<xsl:when test='$number = 15'>fifteen</xsl:when>
<xsl:when test='$number = 16'>sixteen</xsl:when>
<xsl:when test='$number = 17'>seventeen</xsl:when>
<xsl:when test='$number = 18'>eighteen</xsl:when>
<xsl:when test='$number = 19'>nineteen</xsl:when>
<xsl:when test='$number = 20'>twenty</xsl:when>
<xsl:when test='$number = 30'>thirty</xsl:when>
<xsl:when test='$number = 40'>forty</xsl:when>
<xsl:when test='$number = 50'>fifty</xsl:when>
<xsl:when test='$number = 60'>sixty</xsl:when>
<xsl:when test='$number = 70'>seventy</xsl:when>
<xsl:when test='$number = 80'>eighty</xsl:when>
<xsl:when test='$number = 90'>ninety</xsl:when>
<xsl:when test='$number &lt; 100'>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor($number div 10) * 10'/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:call-template name='math:number-as-word'>
<xsl:with-param name='number' select='floor(($number mod 10) + 0.1)'/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

229
texml-xsl/node.xsl Normal file
View File

@ -0,0 +1,229 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://xsltsl.org/xsl/documentation/1.0"
xmlns:node="http://xsltsl.org/node"
extension-element-prefixes="doc node">
<doc:reference xmlns="">
<referenceinfo>
<releaseinfo role="meta">
$Id$
</releaseinfo>
<author>
<surname>Ball</surname>
<firstname>Steve</firstname>
</author>
<copyright>
<year>2001</year>
<holder>Steve Ball</holder>
</copyright>
</referenceinfo>
<title>Node Templates</title>
<partintro>
<section>
<title>Introduction</title>
<para>This stylesheet module provides functions for reporting on or manipulating nodes and nodesets.</para>
</section>
</partintro>
</doc:reference>
<doc:template name="node:xpath" xmlns="">
<refpurpose>Returns an XPath location path</refpurpose>
<refdescription>
<para>This template returns an XPath location path that uniquely identifies the given node within the document.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>node</term>
<listitem>
<para>The node to create an XPath for. If this parameter is given as a nodeset, then the first node in the nodeset is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns an XPath location path as a string.</para>
</refreturn>
</doc:template>
<xsl:template name="node:xpath">
<xsl:param name="node" select="."/>
<xsl:choose>
<xsl:when test="$node">
<xsl:for-each select="$node[1]/ancestor-or-self::*">
<xsl:text/>/<xsl:value-of select="name()"/>
<xsl:text/>[<xsl:value-of select="count(preceding-sibling::*[name() = name(current())]) + 1"/>]<xsl:text/>
</xsl:for-each>
<xsl:choose>
<xsl:when test="$node[1]/self::comment()">
<xsl:text>/comment()</xsl:text>
<xsl:text/>[<xsl:value-of select="count($node[1]/preceding-sibling::comment()) + 1" />]<xsl:text/>
</xsl:when>
<xsl:when test="$node[1]/self::processing-instruction()">
<xsl:text>/processing-instruction()</xsl:text>
<xsl:text/>[<xsl:value-of select="count($node[1]/preceding-sibling::processing-instruction()) + 1" />]<xsl:text/>
</xsl:when>
<xsl:when test="$node[1]/self::text()">
<xsl:text>/text()</xsl:text>
<xsl:text/>[<xsl:value-of select="count($node[1]/preceding-sibling::text()) + 1" />]<xsl:text/>
</xsl:when>
<xsl:when test="not($node[1]/..)">
<xsl:text>/</xsl:text>
</xsl:when>
<xsl:when test="count($node[1]/../namespace::* | $node[1]) = count($node[1]/../namespace::*)">
<xsl:text/>/namespace::<xsl:value-of select="name($node[1])" />
</xsl:when>
<xsl:when test="count($node[1]/../@* | $node[1]) = count($node[1]/../@*)">
<xsl:text/>/@<xsl:value-of select="name($node[1])" />
</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:text>/..</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<doc:template name="node:type" xmlns="">
<refpurpose>Return node type</refpurpose>
<refdescription>
<para>Returns the type of a node as a string.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>node</term>
<listitem>
<para>The node to get the type for. If this parameter is given as a nodeset, then the first node in the nodeset is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns node type as a string. Values returned are:</para>
<variablelist>
<varlistentry>
<term>Element</term>
<listitem>
<para><literal>element</literal></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Text Node</term>
<listitem>
<para><literal>text</literal></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Comment</term>
<listitem>
<para><literal>comment</literal></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Processing Instruction</term>
<listitem>
<para><literal>processing instruction</literal></para>
</listitem>
</varlistentry>
</variablelist>
</refreturn>
</doc:template>
<xsl:template name="node:type">
<xsl:param name="node" select="."/>
<xsl:choose>
<xsl:when test="not($node)"/>
<xsl:when test="$node[1]/self::*">
<xsl:text>element</xsl:text>
</xsl:when>
<xsl:when test="$node[1]/self::text()">
<xsl:text>text</xsl:text>
</xsl:when>
<xsl:when test="$node[1]/self::comment()">
<xsl:text>comment</xsl:text>
</xsl:when>
<xsl:when test="$node[1]/self::processing-instruction()">
<xsl:text>processing instruction</xsl:text>
</xsl:when>
<xsl:when test="not($node[1]/parent::*)">
<xsl:text>root</xsl:text>
</xsl:when>
<xsl:when test="count($node[1] | $node[1]/../namespace::*) = count($node[1]/../namespace::*)">
<xsl:text>namespace</xsl:text>
</xsl:when>
<xsl:when test="count($node[1] | $node[1]/../@*) = count($node[1]/../@*)">
<xsl:text>attribute</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
<doc:template name="node:copy" xmlns="">
<refpurpose>Copy Nodes</refpurpose>
<refdescription>
<para>Makes a copy of the given nodes, including attributes and descendants.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>nodes</term>
<listitem>
<para>The nodes to copy.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the copied nodes as a result tree fragment.</para>
</refreturn>
</doc:template>
<xsl:template name='node:copy'>
<xsl:param name='nodes' select='.'/>
<xsl:for-each select='$nodes'>
<xsl:copy>
<xsl:for-each select='@*'>
<xsl:copy/>
</xsl:for-each>
<xsl:for-each select='node()'>
<xsl:call-template name='node:copy'/>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

340
texml-xsl/stdlib.xsl Normal file
View File

@ -0,0 +1,340 @@
<?xml version="1.0"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY version "1.2.1">
]>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://xsltsl.org/xsl/documentation/1.0"
exclude-result-prefixes="doc"
version="1.0">
<xsl:import href="string.xsl"/>
<xsl:import href="date-time.xsl"/>
<xsl:import href="node.xsl"/>
<xsl:import href="uri.xsl"/>
<xsl:import href="markup.xsl"/>
<xsl:import href="math.xsl"/>
<xsl:import href="cmp.xsl"/>
<xsl:import href="svg.xsl"/>
<!--
<xsl:import href="html/html.xsl"/>
<xsl:import href="fo/fo.xsl"/>
-->
<!-- For a new module, add an import element here -->
<xsl:import href="example.xsl"/>
<doc:book xmlns="">
<bookinfo>
<title>XSLT Standard Library</title>
<subtitle>Version &version;</subtitle>
<!-- $Id$ -->
<author>
<surname>Ball</surname>
<firstname>Steve</firstname>
</author>
<copyright>
<year>2004</year>
<year>2002</year>
<holder>Steve Ball</holder>
</copyright>
</bookinfo>
<preface>
<para>The <ulink url="http://www.w3.org/Style/XSL">XSLT</ulink> Standard Library, <acronym>xsltsl</acronym>, provides the XSLT developer with a set of XSLT templates for commonly used functions. These are implemented purely in XSLT, that is they do not use any extensions.</para>
<para><acronym>xsltsl</acronym> is a <ulink url="http://sourceforge.net/projects/xsltsl/">SourceForge project</ulink>.</para>
<para><ulink url="http://sourceforge.net/"><inlinemediaobject>
<imageobject>
<imagedata fileref="sflogo.gif" width="88" height="31"/>
</imageobject>
<textobject>
<phrase>SourceForge Logo</phrase>
</textobject>
</inlinemediaobject></ulink></para>
<para>Goals of the <acronym>xsltsl</acronym> project include:</para>
<itemizedlist>
<listitem>
<para>Provision of a high-quality library of XSLT templates, suitable for inclusion by vendors in XSLT processor software products.</para>
</listitem>
<listitem>
<para>Demonstration of best practice in XSLT stylesheet development and documentation.</para>
</listitem>
<listitem>
<para>Provide examples of various techniques used to develop XSLT stylesheets (ie. a working FAQ).</para>
</listitem>
</itemizedlist>
</preface>
<chapter>
<title>Using The Library</title>
<para>There are two ways of using the library:</para>
<itemizedlist>
<listitem>
<para>Use a local copy of the library.</para>
<orderedlist>
<listitem>
<para>Download the distribution (see below).</para>
</listitem>
<listitem>
<para>Unpack the distribution, using either gunzip/tar or unzip.</para>
</listitem>
<listitem>
<para>In your stylesheet import or include either the main stylesheet, <filename>stdlib.xsl</filename>, or the stylesheet module you wish to use, such as <filename>string.xsl</filename>. This example assumes that the distribution has been extracted into the same directory as your own stylesheet:</para>
<informalexample>
<programlisting><![CDATA[
<xsl:import href="stdlib.xsl"/>
]]></programlisting>
</informalexample>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>Import or include either the main stylesheet, or the stylesheet module you wish to use, directly from the library website; http://xsltsl.sourceforge.net/modules/. The <filename>modules</filename> directory always contains the latest stable release. For example:</para>
<informalexample>
<programlisting><![CDATA[
<xsl:import href="http://xsltsl.sourceforge.net/modules/stdlib.xsl"/>
]]></programlisting>
</informalexample>
<para>Older versions of the library are available in subdirectories. For example, to access version 1.1 of the library use:</para>
<informalexample>
<programlisting><![CDATA[
<xsl:import href="http://xsltsl.sourceforge.net/modules/1.1/stdlib.xsl"/>
]]></programlisting>
</informalexample>
</listitem>
</itemizedlist>
<para>Next, add XML Namespace declarations for the modules you wish to use. For example, to use templates from the string module, your stylesheet should have the following declaration:</para>
<informalexample>
<programlisting><![CDATA[
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://xsltsl.org/string">
<xsl:import href="http://xsltsl.sourceforge.net/modules/stdlib.xsl"/>
]]></programlisting>
</informalexample>
<para>Finally, use a template with the <sgmltag>call-template</sgmltag> element. Most templates require parameters, which are passed using the <sgmltag>with-param</sgmltag> element. For example:</para>
<informalexample>
<programlisting><![CDATA[
<xsl:template match="foo">
<xsl:call-template name="str:subst">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="replace">a word</xsl:with-param>
<xsl:with-param name="with">another word</xsl:with-param>
</xsl:call-template>
</xsl:template>
]]></programlisting>
</informalexample>
</chapter>
<chapter>
<title>Obtaining The Library</title>
<para>The XSLT Standard Library is available for download as either:</para>
<itemizedlist>
<listitem>
<para>Gzip'd tarball: <ulink url="http://prdownloads.sourceforge.net/xsltsl/xsltsl-&version;.tar.gz">http://prdownloads.sourceforge.net/xsltsl/xsltsl-&version;.tar.gz</ulink></para>
</listitem>
<listitem>
<para>Zip file: <ulink url="http://prdownloads.sourceforge.net/xsltsl/xsltsl-&version;.zip">http://prdownloads.sourceforge.net/xsltsl/xsltsl-&version;.zip</ulink></para>
</listitem>
</itemizedlist>
</chapter>
<chapter>
<title>Getting Involved</title>
<para>Contributions to the project are most welcome, and may be in the form of stylesheet modules, patches, bug reports or sample code. Any contributed code must use the LGPL license to be accepted into the library.</para>
<para>See the SourceForge Project Page <ulink url="http://sourceforge.net/projects/xsltsl/">http://sourceforge.net/projects/xsltsl/</ulink> for information on the development of the project. Bug reports may be submitted here.</para>
<para>See the project Web Page <ulink url="http://xsltsl.sourceforge.net/">http://xsltsl.sourceforge.net/</ulink> for documentation.</para>
<para>There are three mailing lists for the project:</para>
<variablelist>
<varlistentry>
<term><email>xsltsl-users@lists.sourceforge.net</email></term>
<listitem>
<para>Discussion of the use of <acronym>xsltsl</acronym>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><email>xsltsl-devel@lists.sourceforge.net</email></term>
<listitem>
<para>Discussion of the development of <acronym>xsltsl</acronym>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><email>xsltsl-announce@lists.sourceforge.net</email></term>
<listitem>
<para>Project announcements.</para>
</listitem>
</varlistentry>
</variablelist>
</chapter>
<chapter>
<title>XML Namespaces</title>
<para>Apart from the XSLT XML Namespace (http://www.w3.org/1999/XSL/Transform), <acronym>xsltsl</acronym> employs a number of XML Namespaces to allow inclusion of the library in developer stylesheets. In addition, documentation is defined in a separate namespace.</para>
<para>Each module is allocated a namespace URI by appending the module name to the URI for the project, http://xsltsl.org/. For example, the string module has the namespace URI http://xsltsl.org/string.</para>
<para>All documentation is written using an <ulink url="docbook-extensions.html">extension</ulink> of <ulink url="http://www.docbook.org/">DocBook</ulink> designed for <ulink url="docbook-extensions.html">embedding DocBook into XSLT stylesheets</ulink>. The namespace URI for DocBook embedded in stylesheets is http://xsltsl.org/xsl/documentation/1.0</para>
</chapter>
<chapter>
<title>Engineering Standards</title>
<para>In order to maintain a high engineering standard, all modules and contributions to the <acronym>xsltsl</acronym> project must adhere to the following coding and documentation standards. Submissions which do not meet (or exceed) this standard will not be accepted.</para>
<itemizedlist>
<listitem>
<para>All stylesheets must be indented, with each level indented by two spaces. NB. a simple stylesheet could be used to enforce/fix this.</para>
</listitem>
<listitem>
<para>Templates are named using a qualified name (QName). The namespace URI for the template's containing stylesheet is assigned as above.</para>
</listitem>
<listitem>
<para>Parameters for templates should use sensible names. Where possible (or if in doubt), follow these conventions:</para>
<itemizedlist>
<listitem>
<para>A parameter containing a single node is named <parametername>node</parametername>. Where more than one parameter contains a single node, the suffix <parametername>Node</parametername> is appended to the parameter name, eg. <parametername>referenceNode</parametername></para>
</listitem>
<listitem>
<para>A parameter which potentially contains multiple nodes is named <parametername>nodes</parametername>. Where more than one parameter potentially contains multiple nodes, the suffix <parametername>Nodes</parametername> is appended to the parameter name, eg. <parametername>copyNodes</parametername></para>
</listitem>
<listitem>
<para>A parameter which contains a string value is named <parametername>text</parametername>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>All templates in each stylesheet must be documented. A template is documented as a <ulink url="http://www.docbook.org/">DocBook</ulink> RefEntry.</para>
</listitem>
<listitem>
<para>Every stylesheet must include a test suite. The test system is in the <filename>test</filename> subdirectory. See <ulink url="test/test.html">test/test.html</ulink> for further details.</para>
</listitem>
</itemizedlist>
<para>An <ulink url="example.xsl">example stylesheet</ulink> has been provided, which acts as a template for new stylesheet modules.</para>
</chapter>
<chapter>
<title>Related Work</title>
<para>The <ulink url="http://www.exslt.org/">EXSLT</ulink> project is creating a library to standardise extension functions. The XSLT Standard Library is complementary to the EXSLT project.</para>
</chapter>
<chapter>
<title>Reference Documentation</title>
<para>Reference documentation is available for each module.</para>
<section>
<title>String Processing</title>
<itemizedlist>
<listitem>
<para><ulink url="string.html">string.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Nodes</title>
<itemizedlist>
<listitem>
<para><ulink url="node.html">node.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Date/Time Processing</title>
<itemizedlist>
<listitem>
<para><ulink url="date-time.html">date-time.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Mathematics</title>
<itemizedlist>
<listitem>
<para><ulink url="math.html">math.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>URI (Uniform Resource Identifier) Processing</title>
<itemizedlist>
<listitem>
<para><ulink url="uri.html">uri.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Comparing Nodesets</title>
<itemizedlist>
<listitem>
<para><ulink url="cmp.html">cmp.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Generating XML Markup</title>
<itemizedlist>
<listitem>
<para><ulink url="markup.html">markup.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Presentation Media Support</title>
<itemizedlist>
<listitem>
<para>Scalable Vector Graphics: <ulink url="svg.html">svg.xsl</ulink></para>
</listitem>
<!--
<listitem>
<para><ulink url="html/html.html">html/html.xsl</ulink></para>
</listitem>
<listitem>
<para><ulink url="fo/fo.html">fo/fo.xsl</ulink></para>
</listitem>
-->
</itemizedlist>
</section>
<section>
<title>Example</title>
<!-- Add a new module in a similar fashion -->
<itemizedlist>
<listitem>
<para><ulink url="example.html">example.xsl</ulink></para>
</listitem>
</itemizedlist>
</section>
</chapter>
</doc:book>
</xsl:stylesheet>

1233
texml-xsl/string.xsl Normal file

File diff suppressed because one or more lines are too long

1
texml-xsl/svg.xsl Normal file

File diff suppressed because one or more lines are too long

580
texml-xsl/uri.xsl Normal file
View File

@ -0,0 +1,580 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
extension-element-prefixes="doc"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://xsltsl.org/xsl/documentation/1.0"
xmlns:uri="http://xsltsl.org/uri"
>
<doc:reference xmlns="">
<referenceinfo>
<releaseinfo role="meta">
$Id$
</releaseinfo>
<author>
<surname>Diamond</surname>
<firstname>Jason</firstname>
</author>
<copyright>
<year>2001</year>
<holder>Jason Diamond</holder>
</copyright>
</referenceinfo>
<title>URI (Uniform Resource Identifier) Processing</title>
<partintro>
<section>
<title>Introduction</title>
<para>This module provides templates for processing URIs (Uniform Resource Identifers).</para>
</section>
</partintro>
</doc:reference>
<doc:template name="uri:is-absolute-uri" xmlns="">
<refpurpose>Determines if a URI is absolute or relative.</refpurpose>
<refdescription>
<para>Absolute URIs start with a scheme (like "http:" or "mailto:").</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>uri</term>
<listitem>
<para>An absolute or relative URI.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns 'true' if the URI is absolute or '' if it's not.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:is-absolute-uri">
<xsl:param name="uri"/>
<xsl:if test="contains($uri, ':')">
<xsl:value-of select="true()"/>
</xsl:if>
</xsl:template>
<doc:template name="uri:get-uri-scheme" xmlns="">
<refpurpose>Gets the scheme part of a URI.</refpurpose>
<refdescription>
<para>The ':' is not part of the scheme.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>uri</term>
<listitem>
<para>An absolute or relative URI.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the scheme (without the ':') or '' if the URI is relative.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:get-uri-scheme">
<xsl:param name="uri"/>
<xsl:if test="contains($uri, ':')">
<xsl:value-of select="substring-before($uri, ':')"/>
</xsl:if>
</xsl:template>
<doc:template name="uri:get-uri-authority" xmlns="">
<refpurpose>Gets the authority part of a URI.</refpurpose>
<refdescription>
<para>The authority usually specifies the host machine for a resource. It always follows '//' in a typical URI.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>uri</term>
<listitem>
<para>An absolute or relative URI.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the authority (without the '//') or '' if the URI has no authority.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:get-uri-authority">
<xsl:param name="uri"/>
<xsl:variable name="a">
<xsl:choose>
<xsl:when test="contains($uri, ':')">
<xsl:if test="substring(substring-after($uri, ':'), 1, 2) = '//'">
<xsl:value-of select="substring(substring-after($uri, ':'), 3)"/>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="substring($uri, 1, 2) = '//'">
<xsl:value-of select="substring($uri, 3)"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($a, '/')">
<xsl:value-of select="substring-before($a, '/')" />
</xsl:when>
<xsl:when test="contains($a, '?')">
<xsl:value-of select="substring-before($a, '?')" />
</xsl:when>
<xsl:when test="contains($a, '#')">
<xsl:value-of select="substring-before($a, '#')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$a" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<doc:template name="uri:get-uri-path" xmlns="">
<refpurpose>Gets the path part of a URI.</refpurpose>
<refdescription>
<para>The path usually comes after the '/' in a URI.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>uri</term>
<listitem>
<para>An absolute or relative URI.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the path (with any leading '/') or '' if the URI has no path.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:get-uri-path">
<xsl:param name="uri"/>
<xsl:variable name="p">
<xsl:choose>
<xsl:when test="contains($uri, '//')">
<xsl:if test="contains(substring-after($uri, '//'), '/')">
<xsl:value-of select="concat('/', substring-after(substring-after($uri, '//'), '/'))"/>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains($uri, ':')">
<xsl:value-of select="substring-after($uri, ':')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$uri"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($p, '?')">
<xsl:value-of select="substring-before($p, '?')" />
</xsl:when>
<xsl:when test="contains($p, '#')">
<xsl:value-of select="substring-before($p, '#')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$p" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<doc:template name="uri:get-uri-query" xmlns="">
<refpurpose>Gets the query part of a URI.</refpurpose>
<refdescription>
<para>The query comes after the '?' in a URI.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>uri</term>
<listitem>
<para>An absolute or relative URI.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the query (without the '?') or '' if the URI has no query.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:get-uri-query">
<xsl:param name="uri"/>
<xsl:variable name="q" select="substring-after($uri, '?')"/>
<xsl:choose>
<xsl:when test="contains($q, '#')">
<xsl:value-of select="substring-before($q, '#')"/>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$q"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<doc:template name="uri:get-uri-fragment" xmlns="">
<refpurpose>Gets the fragment part of a URI.</refpurpose>
<refdescription>
<para>The fragment comes after the '#' in a URI.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>uri</term>
<listitem>
<para>An absolute or relative URI.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>Returns the fragment (without the '#') or '' if the URI has no fragment.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:get-uri-fragment">
<xsl:param name="uri"/>
<xsl:value-of select="substring-after($uri, '#')"/>
</xsl:template>
<doc:template name="uri:resolve-uri" xmlns="">
<refpurpose>Resolves a URI reference against a base URI.</refpurpose>
<refdescription>
<para>This template follows the guidelines specified by <ulink url="ftp://ftp.isi.edu/in-notes/rfc2396.txt">RFC 2396</ulink>.</para>
</refdescription>
<refparameter>
<variablelist>
<varlistentry>
<term>reference</term>
<listitem>
<para>A (potentially relative) URI reference.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>base</term>
<listitem>
<para>The base URI.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>document</term>
<listitem>
<para>The URI of the current document. This defaults to the value of the base URI if not specified.</para>
</listitem>
</varlistentry>
</variablelist>
</refparameter>
<refreturn>
<para>The "combined" URI.</para>
</refreturn>
</doc:template>
<xsl:template name="uri:resolve-uri">
<xsl:param name="reference"/>
<xsl:param name="base"/>
<xsl:param name="document" select="$base"/>
<xsl:variable name="reference-scheme">
<xsl:call-template name="uri:get-uri-scheme">
<xsl:with-param name="uri" select="$reference"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="reference-authority">
<xsl:call-template name="uri:get-uri-authority">
<xsl:with-param name="uri" select="$reference"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="reference-path">
<xsl:call-template name="uri:get-uri-path">
<xsl:with-param name="uri" select="$reference"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="reference-query">
<xsl:call-template name="uri:get-uri-query">
<xsl:with-param name="uri" select="$reference"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="reference-fragment">
<xsl:call-template name="uri:get-uri-fragment">
<xsl:with-param name="uri" select="$reference"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="
not(string-length($reference-scheme)) and
not(string-length($reference-authority)) and
not(string-length($reference-path)) and
not(string-length($reference-query))"
>
<xsl:choose>
<xsl:when test="contains($document, '?')">
<xsl:value-of select="substring-before($document, '?')"/>
</xsl:when>
<xsl:when test="contains($document, '#')">
<xsl:value-of select="substring-before($document, '#')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$document"/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="string-length($reference-fragment)">
<xsl:value-of select="concat('#', $reference-fragment)"/>
</xsl:if>
</xsl:when>
<xsl:when test="string-length($reference-scheme)">
<xsl:value-of select="$reference"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="base-scheme">
<xsl:call-template name="uri:get-uri-scheme">
<xsl:with-param name="uri" select="$base"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="base-authority">
<xsl:call-template name="uri:get-uri-authority">
<xsl:with-param name="uri" select="$base"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="base-path">
<xsl:call-template name="uri:get-uri-path">
<xsl:with-param name="uri" select="$base"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="base-query">
<xsl:call-template name="uri:get-uri-query">
<xsl:with-param name="uri" select="$base"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="base-fragment">
<xsl:call-template name="uri:get-uri-fragment">
<xsl:with-param name="uri" select="$base"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="result-authority">
<xsl:choose>
<xsl:when test="string-length($reference-authority)">
<xsl:value-of select="$reference-authority"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$base-authority"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="result-path">
<xsl:choose>
<!-- don't normalize absolute paths -->
<xsl:when test="starts-with($reference-path, '/')">
<xsl:value-of select="$reference-path" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="uri:normalize-path">
<xsl:with-param name="path">
<xsl:if test="string-length($reference-authority) = 0 and substring($reference-path, 1, 1) != '/'">
<xsl:call-template name="uri:get-path-without-file">
<xsl:with-param name="path-with-file" select="$base-path"/>
</xsl:call-template>
<xsl:value-of select="'/'"/>
</xsl:if>
<xsl:value-of select="$reference-path"/>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="concat($base-scheme, '://', $result-authority, $result-path)"/>
<xsl:if test="string-length($reference-query)">
<xsl:value-of select="concat('?', $reference-query)"/>
</xsl:if>
<xsl:if test="string-length($reference-fragment)">
<xsl:value-of select="concat('#', $reference-fragment)"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="uri:get-path-without-file">
<xsl:param name="path-with-file" />
<xsl:param name="path-without-file" />
<xsl:choose>
<xsl:when test="contains($path-with-file, '/')">
<xsl:call-template name="uri:get-path-without-file">
<xsl:with-param name="path-with-file" select="substring-after($path-with-file, '/')" />
<xsl:with-param name="path-without-file">
<xsl:choose>
<xsl:when test="$path-without-file">
<xsl:value-of select="concat($path-without-file, '/', substring-before($path-with-file, '/'))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($path-with-file, '/')" />
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$path-without-file" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="uri:normalize-path">
<xsl:param name="path"/>
<xsl:param name="result" select="''"/>
<xsl:choose>
<xsl:when test="string-length($path)">
<xsl:choose>
<xsl:when test="$path = '/'">
<xsl:value-of select="concat($result, '/')"/>
</xsl:when>
<xsl:when test="$path = '.'">
<xsl:value-of select="concat($result, '/')"/>
</xsl:when>
<xsl:when test="$path = '..'">
<xsl:call-template name="uri:get-path-without-file">
<xsl:with-param name="path-with-file" select="$result"/>
</xsl:call-template>
<xsl:value-of select="'/'"/>
</xsl:when>
<xsl:when test="contains($path, '/')">
<!-- the current segment -->
<xsl:variable name="s" select="substring-before($path, '/')"/>
<!-- the remaining path -->
<xsl:variable name="p">
<xsl:choose>
<xsl:when test="substring-after($path, '/') = ''">
<xsl:value-of select="'/'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-after($path, '/')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$s = ''">
<xsl:call-template name="uri:normalize-path">
<xsl:with-param name="path" select="$p"/>
<xsl:with-param name="result" select="$result"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$s = '.'">
<xsl:call-template name="uri:normalize-path">
<xsl:with-param name="path" select="$p"/>
<xsl:with-param name="result" select="$result"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$s = '..'">
<xsl:choose>
<xsl:when test="string-length($result) and (substring($result, string-length($result) - 2) != '/..')">
<xsl:call-template name="uri:normalize-path">
<xsl:with-param name="path" select="$p"/>
<xsl:with-param name="result">
<xsl:call-template name="uri:get-path-without-file">
<xsl:with-param name="path-with-file" select="$result"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="uri:normalize-path">
<xsl:with-param name="path" select="$p"/>
<xsl:with-param name="result" select="concat($result, '/..')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="uri:normalize-path">
<xsl:with-param name="path" select="$p"/>
<xsl:with-param name="result" select="concat($result, '/', $s)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($result, '/', $path)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

90
tools/archive.py Executable file
View File

@ -0,0 +1,90 @@
#!/usr/bin/env python3
import pathlib
import shutil
import sys
import xml.etree.ElementTree as etree
from datetime import datetime, timedelta
from xeplib import load_xepinfos, Status
def main():
import argparse
parser = argparse.ArgumentParser(
description="Show the XEPs which need to be changed to deferred."
)
parser.add_argument(
"old",
type=argparse.FileType("rb"),
help="Old XEP list"
)
parser.add_argument(
"new",
type=argparse.FileType("rb"),
help="New XEP list"
)
parser.add_argument(
"-d", "--xeps-dir",
type=pathlib.Path,
default=pathlib.Path.cwd() / "build",
help="Path to the built XEPs (defaults to ./build)"
)
parser.add_argument(
"-a", "--attic",
type=pathlib.Path,
default=pathlib.Path.cwd() / '../xep-attic/content/',
help="Path to the attic (defaults to ../xep-attic/content/)"
)
args = parser.parse_args()
with args.old as f:
old_tree = etree.parse(f)
old_accepted, _ = load_xepinfos(old_tree)
with args.new as f:
new_tree = etree.parse(f)
new_accepted, _ = load_xepinfos(new_tree)
changed = False
for xep, new_info in new_accepted.items():
old_version = old_accepted.get(xep, {}).get("last_revision", {}).get(
"version"
)
new_version = new_info["last_revision"]["version"]
if old_version == new_version:
continue
curr_file = args.xeps_dir / "xep-{:04d}.html".format(xep)
attic_file = args.attic / "xep-{:04d}-{}.html".format(xep, new_version)
print("XEP-{:04d}:".format(xep), old_version, "->", new_version)
shutil.copy(str(curr_file), str(attic_file))
changed = True
if changed:
print(
"{}: do not forget to commit & push the attic!".format(
sys.argv[0]
),
file=sys.stderr
)
else:
print("{}: nothing to do".format(sys.argv[0]),
file=sys.stderr)
if __name__ == "__main__":
main()

125
tools/deferrals.py Executable file
View File

@ -0,0 +1,125 @@
#!/usr/bin/env python3
import re
import xml.etree.ElementTree as etree
from datetime import datetime, timedelta
from xeplib import load_xepinfos, Status
def get_deferred(accepted):
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
threshold = now.replace(year=now.year - 1)
for number, info in sorted(accepted.items()):
if info["status"] == Status.EXPERIMENTAL and "last_revision" in info:
last_update = info["last_revision"]["date"]
if last_update <= threshold:
yield info
EXPERIMENTAL_STATUS = "<status>Experimental</status>"
DEFERRED_STATUS = "<status>Deferred</status>"
REVISION_RE = re.compile(r"\s+<revision>")
REVISION_TEMPLATE = """
<revision>
<version>{version}</version>
<date>{now:%Y-%m-%d}</date>
<initials>XEP Editor ({initials})</initials>
<remark>Defer due to lack of activity.</remark>
</revision>"""
def defer_xep(number, last_version, initials):
filename = "xep-{:04d}.xml".format(number)
with open(filename, "r") as f:
xep_text = f.read()
if EXPERIMENTAL_STATUS not in xep_text:
raise ValueError("cannot find experimental status in XEP text")
# this is so incredibly evil ...
xep_text = xep_text.replace(EXPERIMENTAL_STATUS, DEFERRED_STATUS, 1)
revision_match = REVISION_RE.search(xep_text)
version = last_version.split(".")
if len(version) == 1:
version.append("1")
else:
version[1] = str(int(version[1]) + 1)
del version[2:]
xep_text = (
xep_text[:revision_match.start()] +
REVISION_TEMPLATE.format(
now=datetime.utcnow(),
version=".".join(version),
initials=initials,
) + xep_text[revision_match.start():]
)
with open(filename, "w") as f:
f.write(xep_text)
f.flush()
def main():
import argparse
parser = argparse.ArgumentParser(
description="Show the XEPs which need to be changed to deferred."
)
parser.add_argument(
"-l", "--xeplist",
type=argparse.FileType("rb"),
default=None,
help="XEP list to use (defaults to ./build/xeplist.xml)"
)
parser.add_argument(
"-v", "--verbose",
help="Print additional metadata for deferred XEPs",
action="store_true",
default=False,
)
parser.add_argument(
"-m", "--modify",
default=False,
metavar="INITIALS",
help="Modify the to-be-deferred XEPs in-place and use the given "
"INITIALS in the remarks."
)
args = parser.parse_args()
if args.xeplist is None:
args.xeplist = open("./build/xeplist.xml", "rb")
with args.xeplist as f:
tree = etree.parse(f)
accepted, _ = load_xepinfos(tree)
deferred = list(get_deferred(accepted))
for deferred_info in deferred:
if args.modify:
defer_xep(deferred_info["number"],
deferred_info["last_revision"]["version"],
args.modify)
if args.verbose:
print(
"XEP-{info[number]:04d}: {info[title]} "
"(last update {info[last_revision][date]:%Y-%m-%d})".format(
info=deferred_info
)
)
else:
print(deferred_info["number"])
if __name__ == "__main__":
main()

217
tools/extract-metadata.py Executable file
View File

@ -0,0 +1,217 @@
#!/usr/bin/env python3
import pathlib
import sys
import xml.dom.minidom
import xml.etree.ElementTree as etree
from xeplib import (
minidom_find_child,
minidom_find_header,
minidom_get_text,
minidom_children,
)
DESCRIPTION = """\
Extract a list of XEPs with metadata from the xeps repository."""
EPILOG = """"""
def open_xml(f):
return xml.dom.minidom.parse(f)
def extract_xep_metadata(document):
header = minidom_find_header(document)
latest_revision = minidom_find_child(header, "revision")
if latest_revision is not None:
last_revision_version = minidom_get_text(
minidom_find_child(latest_revision, "version")
)
last_revision_date = minidom_get_text(
minidom_find_child(latest_revision, "date")
)
remark_el = minidom_find_child(latest_revision, "remark")
last_revision_remark = None
if remark_el is not None:
remark_children = minidom_children(remark_el)
if len(remark_children) == 1 and remark_children[0].tagName == "p":
last_revision_remark = minidom_get_text(remark_children[0])
elif len(remark_children) == 0:
last_revision_remark = minidom_get_text(remark_el) or None
if last_revision_remark is not None:
initials_el = minidom_find_child(latest_revision, "initials")
last_revision_initials = initials_el and minidom_get_text(
initials_el
)
else:
last_revision_initials = None
else:
last_revision_version = None
last_revision_date = None
last_revision_remark = None
last_revision_initials = None
status = minidom_get_text(minidom_find_child(header, "status"))
type_ = minidom_get_text(minidom_find_child(header, "type"))
abstract = " ".join(minidom_get_text(
minidom_find_child(header, "abstract")
).split())
sig_el = minidom_find_child(header, "sig")
if sig_el is None:
sig = None
else:
sig = minidom_get_text(sig_el)
shortname = minidom_get_text(minidom_find_child(header, "shortname"))
if shortname.replace("-", " ").replace("_", " ").lower() in [
"not yet assigned", "n/a", "none", "to be assigned",
"to be issued"]:
shortname = None
title = minidom_get_text(minidom_find_child(header, "title"))
approver_el = minidom_find_child(header, "approver")
if approver_el is not None:
approver = minidom_get_text(approver_el)
else:
approver = "Board" if type_ == "Procedural" else "Council"
return {
"last_revision": {
"version": last_revision_version,
"date": last_revision_date,
"initials": last_revision_initials,
"remark": last_revision_remark,
},
"status": status,
"type": type_,
"sig": sig,
"abstract": abstract,
"shortname": shortname,
"title": title,
"approver": approver,
}
def text_element(tag, text):
el = etree.Element(tag)
el.text = text
return el
def make_metadata_element(number, metadata, accepted, *, protoname=None):
result = etree.Element("xep")
result.append(text_element("number", number))
result.append(text_element("title", metadata["title"]))
result.append(text_element("abstract", metadata["abstract"]))
result.append(text_element("type", metadata["type"]))
result.append(text_element("status", metadata["status"]))
result.append(text_element("approver", metadata["approver"]))
if metadata["shortname"] is not None:
result.append(text_element("shortname", metadata["shortname"]))
if metadata["last_revision"]["version"] is not None:
last_revision = metadata["last_revision"]
revision_el = etree.Element("last-revision")
revision_el.append(text_element("date", last_revision["date"]))
revision_el.append(text_element("version", last_revision["version"]))
if last_revision["initials"]:
revision_el.append(text_element("initials",
last_revision["initials"]))
if last_revision["remark"]:
revision_el.append(text_element("remark",
last_revision["remark"]))
result.append(revision_el)
if metadata["sig"] is not None:
result.append(
text_element("sig", metadata["sig"])
)
if accepted:
result.set("accepted", "true")
else:
result.set("accepted", "false")
if protoname is not None:
result.append(text_element("proto-name", protoname))
return result
def parse_checked_and_print_error(xepfile):
try:
with xepfile.open("rb") as f:
return open_xml(f)
except xml.parsers.expat.ExpatError as exc:
print("{}: {}".format(xepfile, exc), file=sys.stderr)
return None
def main():
import argparse
import sys
parser = argparse.ArgumentParser(
description=DESCRIPTION,
epilog=EPILOG,
)
parser.add_argument(
"xepdir",
nargs="?",
type=pathlib.Path,
default=pathlib.Path.cwd(),
help="Directory where the XEP XMLs are. Defaults to current directory."
)
args = parser.parse_args()
tree = etree.Element("xep-infos")
has_error = False
for xepfile in args.xepdir.glob("xep-*.xml"):
number = xepfile.name.split("-", 1)[1].split(".", 1)[0]
try:
number = str(int(number))
except ValueError:
continue
parsed = parse_checked_and_print_error(xepfile)
if parsed is None:
has_error = True
continue
tree.append(make_metadata_element(
number,
extract_xep_metadata(parsed),
True,
))
for xepfile in (args.xepdir / "inbox").glob("*.xml"):
protoname = xepfile.name.rsplit(".", 1)[0]
parsed = parse_checked_and_print_error(xepfile)
if parsed is None:
has_error = True
continue
tree.append(make_metadata_element(
"xxxx",
extract_xep_metadata(parsed),
False,
protoname=protoname
))
if has_error:
sys.exit(2)
sys.stdout.buffer.raw.write(etree.tostring(tree))
if __name__ == "__main__":
main()

455
tools/send-updates.py Executable file
View File

@ -0,0 +1,455 @@
#!/usr/bin/env python3
import configparser
import getpass
import itertools
import email.message
import os
import smtplib
import sys
import textwrap
from datetime import datetime
import xml.etree.ElementTree as etree
from xeplib import Status, Action, load_xepinfos
DESCRIPTION = """\
Send email updates for XEP changes based on the difference between two \
xeplist files."""
EPILOG = """\
Configuration file contents:
[smtp]
host=<smtp server to send through>
port=587
user=<optional: user name to authenticate with>
password=<optional: password to authn. with>
from=<address to send from>
If user is omitted, anonymous mail sending is attempted.
If options are missing from the configuration file and the standard input and \
standard output are a terminal, the script interactively asks for the option \
values. If no terminal is connected, the script exits with an error instead."""
XEP_URL_PREFIX = "https://xmpp.org/extensions/"
MAIL_PROTO_TEMPLATE = """\
The XMPP Extensions Editor has received a proposal for a new XEP.
Title: {info[title]}
Abstract:
{info[abstract]}
URL: {url}
The {approver} will decide in the next two weeks whether to accept this \
proposal as an official XEP."""
SUBJECT_PROTO_TEMPLATE = "Proposed XMPP Extension: {info[title]}"
MAIL_NONPROTO_TEMPLATE = """\
Version {info[last_revision][version]} of XEP-{info[number]:04d} \
({info[title]}) has been released.
Abstract:
{info[abstract]}
Changelog:
{changelog}
URL: {url}"""
MAIL_DEFER_TEMPLATE = """\
XEP-{info[number]:04d} ({info[title]}) has been Deferred because of inactivity.
Abstract:
{info[abstract]}
URL: {url}
If and when a new revision of this XEP is published, its status will be \
changed back to Experimental.
"""
SUBJECT_NONPROTO_TEMPLATE = \
"{action.value}: XEP-{info[number]:04d} ({info[title]})"
def dummy_info(number):
return {
"status": None,
"accepted": False,
"number": number,
}
def diff_infos(old, new):
if old["status"] != new["status"]:
if new["status"] == Status.PROTO:
return Action.PROTO
elif old["status"] is None:
return Action.NEW
elif (old["status"] == Status.DEFERRED and
new["status"] == Status.EXPERIMENTAL):
return Action.UPDATE
else:
return Action.fromstatus(new["status"])
old_version = old.get("last_revision", {}).get("version")
new_version = new.get("last_revision", {}).get("version")
if old_version != new_version:
return Action.UPDATE
return None
def wraptext(text):
return "\n".join(
itertools.chain(
*[textwrap.wrap(line) if line else [line] for line in text.split("\n")]
)
)
def make_proto_mail(info):
kwargs = {
"info": info,
"approver": info["approver"],
"url": "{}inbox/{}.html".format(
XEP_URL_PREFIX,
info["protoname"],
),
}
mail = email.message.EmailMessage()
mail["Subject"] = SUBJECT_PROTO_TEMPLATE.format(**kwargs)
mail["XSF-XEP-Action"] = "PROTO"
mail["XSF-XEP-Title"] = info["title"]
mail["XSF-XEP-Type"] = info["type"]
mail["XSF-XEP-Status"] = info["status"].value
mail["XSF-XEP-Url"] = kwargs["url"]
mail["XSF-XEP-Approver"] = kwargs["approver"]
mail.set_content(
wraptext(MAIL_PROTO_TEMPLATE.format(**kwargs)),
"plain",
"utf-8",
)
return mail
def make_nonproto_mail(action, info):
last_revision = info.get("last_revision")
changelog = "(see in-document revision history)"
if last_revision is not None:
remark = last_revision.get("remark")
initials = last_revision.get("initials")
if remark and initials:
changelog = "{} ({})".format(remark, initials)
kwargs = {
"info": info,
"changelog": changelog,
"action": action,
"url": "{}xep-{:04d}.html".format(
XEP_URL_PREFIX,
info["number"],
),
}
body_template = MAIL_NONPROTO_TEMPLATE
if action == Action.DEFER:
body_template = MAIL_DEFER_TEMPLATE
mail = email.message.EmailMessage()
mail["Subject"] = SUBJECT_NONPROTO_TEMPLATE.format(**kwargs)
mail["XSF-XEP-Action"] = action.value
mail["XSF-XEP-Title"] = info["title"]
mail["XSF-XEP-Type"] = info["type"]
mail["XSF-XEP-Status"] = info["status"].value
mail["XSF-XEP-Number"] = "{:04d}".format(info["number"])
mail["XSF-XEP-Url"] = kwargs["url"]
mail.set_content(
wraptext(body_template.format(**kwargs)),
"plain",
"utf-8",
)
return mail
def get_or_ask(config, section, name, prompt):
try:
return config.get(section, name)
except (configparser.NoSectionError,
configparser.NoOptionError):
return input(prompt)
def interactively_extend_smtp_config(config):
try:
host = config.get("smtp", "host")
except (configparser.NoSectionError,
configparser.NoOptionError):
host = input("SMTP server: ").strip()
port = int(input("SMTP port (blank for 587): ").strip() or "587")
user = input(
"SMTP user (leave blank for anon): "
).strip() or None
if user:
password = getpass.getpass()
else:
password = None
else:
port = config.getint("smtp", "port", fallback=587)
user = config.get("smtp", "user", fallback=None)
password = config.get("smtp", "password", fallback=None)
try:
from_ = config.get("smtp", "from")
except (configparser.NoSectionError,
configparser.NoOptionError):
from_ = input("From address: ").strip()
if not config.has_section("smtp"):
config.add_section("smtp")
config.set("smtp", "host", host)
config.set("smtp", "port", str(port))
if user:
config.set("smtp", "user", user)
if password is None:
password = getpass.getpass()
config.set("smtp", "password", password)
config.set("smtp", "from", from_)
def choose(prompt, options, *,
eof=EOFError,
keyboard_interrupt=KeyboardInterrupt):
while True:
try:
choice = input(prompt).strip()
except EOFError:
if eof is EOFError:
raise
return eof
except KeyboardInterrupt:
if keyboard_interrupt is KeyboardInterrupt:
raise
return keyboard_interrupt
if choice not in options:
print("invalid choice. please enter one of: {}".format(
", ".join(map(str, options))
))
continue
return choice
def make_smtpconn(config):
host = config.get("smtp", "host")
port = config.getint("smtp", "port")
user = config.get("smtp", "user", fallback=None)
password = config.get("smtp", "password", fallback=None)
conn = smtplib.SMTP(host, port)
conn.starttls()
if user is not None:
conn.login(user, password)
return conn
def make_fake_smtpconn():
class Fake:
def send_message(self, mail):
print("---8<---")
print(mail.as_string())
print("--->8---")
def close(self):
pass
return Fake()
def main():
import argparse
parser = argparse.ArgumentParser(
description=wraptext(DESCRIPTION),
epilog=wraptext(EPILOG),
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
"-c", "--config",
metavar="FILE",
type=argparse.FileType("r"),
help="Configuration file",
)
parser.add_argument(
"-y",
dest="ask_confirmation",
default=True,
action="store_false",
help="'I trust this script to do the right thing and send emails"
"without asking for confirmation.'"
)
parser.add_argument(
"--no-proto",
dest="process_proto",
default=True,
action="store_false",
help="Disable processing of ProtoXEPs.",
)
parser.add_argument(
"-n", "--dry-run",
dest="dry_run",
action="store_true",
default=False,
help="Instead of sending emails, print them to stdout (implies -y)",
)
parser.add_argument(
"old",
type=argparse.FileType("rb"),
help="Old xep-infos XML file",
)
parser.add_argument(
"new",
type=argparse.FileType("rb"),
help="New xep-infos XML file",
)
parser.add_argument(
"to",
nargs="+",
help="The mail addresses to send the update mails to."
)
args = parser.parse_args()
can_be_interactive = (
os.isatty(sys.stdin.fileno()) and
os.isatty(sys.stdout.fileno())
)
if args.dry_run:
args.ask_confirmation = False
if args.ask_confirmation and not can_be_interactive:
print("Cannot ask for confirmation (stdio is not a TTY), but -y is",
"not given either. Aborting.", sep="\n", file=sys.stderr)
sys.exit(2)
config = configparser.ConfigParser()
if args.config is not None:
config.read_file(args.config)
with args.old as f:
tree = etree.parse(f)
old_accepted, old_proto = load_xepinfos(tree)
with args.new as f:
tree = etree.parse(f)
new_accepted, new_proto = load_xepinfos(tree)
old_xeps = set(old_accepted.keys())
new_xeps = set(new_accepted.keys())
common_xeps = old_xeps & new_xeps
added_xeps = new_xeps - old_xeps
added_protos = set(new_proto.keys()) - set(old_proto.keys())
updates = []
for common_xep in common_xeps:
old_info = old_accepted[common_xep]
new_info = new_accepted[common_xep]
action = diff_infos(old_info, new_info)
if action is not None:
updates.append((common_xep, action, new_info))
for added_xep in added_xeps:
old_info = dummy_info(added_xep)
new_info = new_accepted[added_xep]
action = diff_infos(old_info, new_info)
if action is not None:
updates.append((added_xep, action, new_info))
if args.process_proto:
for added_proto in added_protos:
old_info = dummy_info('xxxx')
new_info = new_proto[added_proto]
action = diff_infos(old_info, new_info)
if action is not None:
updates.append((added_proto, action, new_info))
if args.dry_run:
smtpconn = make_fake_smtpconn()
else:
if can_be_interactive:
interactively_extend_smtp_config(config)
try:
smtpconn = make_smtpconn(config)
except (configparser.NoSectionError,
configparser.NoOptionError) as exc:
print("Missing configuration: {}".format(exc),
file=sys.stderr)
print("(cannot ask for configuration on stdio because it is "
"not a TTY)", file=sys.stderr)
sys.exit(3)
try:
for id_, action, info in updates:
if action == Action.PROTO:
mail = make_proto_mail(info)
else:
mail = make_nonproto_mail(action, info)
mail["Date"] = datetime.utcnow()
mail["From"] = config.get("smtp", "from")
mail["To"] = args.to
if args.ask_confirmation:
print()
print("---8<---")
print(mail.as_string())
print("--->8---")
print()
choice = choose(
"Send this email? [y]es, [n]o, [a]bort: ",
"yna",
eof="a",
)
if choice == "n":
continue
elif choice == "a":
print("Exiting on user request.", file=sys.stderr)
sys.exit(4)
smtpconn.send_message(mail)
finally:
smtpconn.close()
if __name__ == "__main__":
main()

139
tools/xeplib.py Normal file
View File

@ -0,0 +1,139 @@
import enum
import xml.dom.minidom
from datetime import datetime
class Status(enum.Enum):
PROTO = 'ProtoXEP'
EXPERIMENTAL = 'Experimental'
PROPOSED = 'Proposed'
DRAFT = 'Draft'
ACTIVE = 'Active'
FINAL = 'Final'
RETRACTED = 'Retracted'
OBSOLETE = 'Obsolete'
DEFERRED = 'Deferred'
REJECTED = 'Rejected'
DEPRECATED = 'Deprecated'
@classmethod
def fromstr(cls, s):
if s == "Proto" or s.lower() == "protoxep":
s = "ProtoXEP"
return cls(s)
class Action(enum.Enum):
PROTO = "Proposed XMPP Extension"
NEW = "NEW"
DRAFT = "DRAFT"
ACTIVE = "ACTIVE"
FINAL = "FINAL"
RETRACT = "RETRACTED"
OBSOLETE = "OBSOLETED"
DEFER = "DEFERRED"
UPDATE = "UPDATED"
DEPRECATE = "DEPRECATED"
@classmethod
def fromstatus(cls, status):
return {
Status.EXPERIMENTAL: cls.NEW,
Status.DRAFT: cls.DRAFT,
Status.ACTIVE: cls.ACTIVE,
Status.FINAL: cls.FINAL,
Status.RETRACTED: cls.RETRACT,
Status.OBSOLETE: cls.OBSOLETE,
Status.DEPRECATED: cls.DEPRECATE,
Status.DEFERRED: cls.DEFER,
}[status]
def load_xepinfo(el):
accepted = el.get("accepted").lower() == "true"
info = {
"title": el.find("title").text,
"abstract": el.find("abstract").text,
"type": el.find("type").text,
"status": Status.fromstr(el.find("status").text),
"approver": el.find("approver").text,
"accepted": accepted,
}
last_revision_el = el.find("last-revision")
if last_revision_el is not None:
last_revision = {
"version": last_revision_el.find("version").text,
"date": datetime.strptime(
last_revision_el.find("date").text,
"%Y-%m-%d",
),
"initials": None,
"remark": None,
}
initials_el = last_revision_el.find("initials")
if initials_el is not None:
last_revision["initials"] = initials_el.text
remark_el = last_revision_el.find("remark")
if remark_el is not None:
last_revision["remark"] = remark_el.text
info["last_revision"] = last_revision
sig = el.find("sig")
if sig is not None:
info["sig"] = sig.text
if accepted:
info["number"] = int(el.find("number").text)
else:
info["protoname"] = el.find("proto-name").text
return info
def load_xepinfos(tree):
accepted, protos = {}, {}
for info_el in tree.getroot():
info = load_xepinfo(info_el)
if info["accepted"]:
accepted[info["number"]] = info
else:
protos[info["protoname"]] = info
return accepted, protos
def minidom_find_child(elem, child_tag):
for child in elem.childNodes:
if hasattr(child, "tagName") and child.tagName == child_tag:
return child
return None
def minidom_find_header(document):
header = minidom_find_child(document.documentElement, "header")
if header is None:
raise ValueError("cannot find <header/>")
return header
def minidom_get_text(elem):
return "".join(
child.nodeValue
for child in elem.childNodes
if isinstance(child, (xml.dom.minidom.Text,
xml.dom.minidom.CDATASection))
)
def minidom_children(elem):
return [
child for child in elem.childNodes
if isinstance(child, (xml.dom.minidom.Element))
]

View File

@ -219,7 +219,7 @@
</section1>
<section1 topic='XEP Types' anchor='types'>
<p>The five XEP types are described in the following sections.</p>
<p>The approving body for all Standards Track, Informational, and Historical XEPs is the XMPP Council; the approving body for Humorous XEPs in the XMPP Extensions Editor; and the approving body for Procedural XEPs may be either the &BOARD; or the XMPP Council.</p>
<p>The approving body for all Standards Track, Informational, and Historical XEPs is the XMPP Council; the approving body for Humorous XEPs is the XMPP Extensions Editor; and the approving body for Procedural XEPs may be either the &BOARD; or the XMPP Council.</p>
<p>This document focuses primarily on Standards Track XEPs since they are the vehicle for defining new protocols, but also discusses the other XEP types.</p>
<section2 topic='Standards Track' anchor='types-Standards-Track'>
<p>A <span class='ref'>Standards Track XEP</span> defines one of the following:</p>
@ -406,7 +406,7 @@ Experimental ----> Proposed ----> Active
<p>Every XMPP Extension Protocol specification must contain a section entitled "Security Considerations", detailing security concerns or features related to the proposal; in particular, a Standards Track XEP should list the security threats that the protocol addresses and does not address, as well as security issues related to implementation of the protocol and deployment of such implementations. XEP authors should refer to &rfc3552; for helpful information about documenting security considerations and should also confer with the XMPP Extensions Editor and/or XMPP Council regarding this important task.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>Some XMPP Extension Protocols may require interaction with &IANA;. The IANA acts as a clearinghouse to assign and coordinate the use of numerous Internet protocol parameters, such as MIME types and port numbers (e.g., the TCP ports 5222, 5269, and 5280 used by the XMPP developer community are registered with the IANA). Whether or not a XEP requires registration of parameters with the IANA, that fact must be noted and explained in a distinct section of the XEP entitled "IANA Considerations". Registration with the IANA must not occur until the registration has been approbved by the XMPP Council (e.g., by advancement of a XEP to a status of Draft or Active), and must be initiated by the XMPP Registrar in consultation with the XEP author, not by the XEP author directly with the IANA.</p>
<p>Some XMPP Extension Protocols may require interaction with &IANA;. The IANA acts as a clearinghouse to assign and coordinate the use of numerous Internet protocol parameters, such as MIME types and port numbers (e.g., the TCP ports 5222, 5269, and 5280 used by the XMPP developer community are registered with the IANA). Whether or not a XEP requires registration of parameters with the IANA, that fact must be noted and explained in a distinct section of the XEP entitled "IANA Considerations". Registration with the IANA must not occur until the registration has been approved by the XMPP Council (e.g., by advancement of a XEP to a status of Draft or Active), and must be initiated by the XMPP Registrar in consultation with the XEP author, not by the XEP author directly with the IANA.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>The &REGISTRAR; performs a function similar to the IANA, although limited to the XMPP developer community. It does so by reserving protocol namespaces and by uniquely assigning parameters for use in the context of XMPP protocols (for example, the categories and types used in &xep0030;).</p>

View File

@ -36,6 +36,12 @@
&pgmillard;
&reatmon;
&stpeter;
<revision>
<version>2.5rc3</version>
<date>2017-10-03</date>
<initials>th</initials>
<remark><p>XML schema modified so that no ordering is required between disco#info children.</p></remark>
</revision>
<revision>
<version>2.5rc2</version>
<date>2016-10-13</date>
@ -874,8 +880,20 @@ xmpp:romeo@montague.net?disco;type=get;request=items
<xs:element name='query'>
<xs:complexType>
<xs:sequence minOccurs='0'>
<xs:element ref='identity' maxOccurs='unbounded'/>
<xs:element ref='feature' maxOccurs='unbounded'/>
<xs:choice>
<xs:sequence>
<xs:element ref='feature' maxOccurs='unbounded'/>
<xs:element ref='identity'/>
</xs:sequence>
<xs:sequence>
<xs:element ref='identity' maxOccurs='unbounded'/>
<xs:element ref='feature'/>
</xs:sequence>
</xs:choice>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='identity'/>
<xs:element ref='feature'/>
</xs:choice>
</xs:sequence>
<xs:attribute name='node' type='xs:string' use='optional'/>
</xs:complexType>

View File

@ -45,6 +45,22 @@
</schemaloc>
<registry/>
&stpeter;
<revision>
<version>1.29</version>
<date>2017-09-01</date>
<initials>gl</initials>
<remark>
<p>Clarify wording for a client re-syncing to a MUC</p>
</remark>
</revision>
<revision>
<version>1.28</version>
<date>2017-05-31</date>
<initials>gl</initials>
<remark>
<p>Introduce &lt;x/&gt; tag in MUC-PMs to support better Carbon delivery.</p>
</remark>
</revision>
<revision>
<version>1.27.1</version>
<date>2016-12-03</date>
@ -1385,6 +1401,7 @@
</presence>
]]></example>
<p>Before attempting to enter the room, a MUC-compliant client SHOULD first discover its reserved room nickname (if any) by following the protocol defined in the <link url='#reservednick'>Discovering Reserved Room Nickname</link> section of this document.</p>
<p>When a MUC service receives an &lt;x/&gt; tagged join stanza from an already-joined client (as identified by the client's full JID), the service should assume that the client lost its synchronization, and therefore it SHOULD send exactly the same stanzas to the client as if it actually just joined the MUC. The server MAY also send a presence update to the other participants according to the received join presence.</p>
</section3>
<section3 topic='Presence Broadcast' anchor='enter-pres'>
@ -1903,6 +1920,8 @@
<section2 topic='Sending a Private Message' anchor='privatemessage'>
<p>Since each occupant has its own occupant JID, an occupant can send a "private message" to a selected occupant via the service by sending a message to the intended recipient's occupant JID. The message type SHOULD be "chat" and MUST NOT be "groupchat", but MAY be left unspecified (i.e., a normal message). This privilege is controlled by the "muc#roomconfig_allowpm" room configuration option.</p>
<p>To allow for proper synchronization of these messages to the user's other clients by &xep0280;, the sending client SHOULD add an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace to the message.</p>
<p><strong>Note:</strong> because this requirement was only added in revision 1.28 of this XEP, receiving entities MUST NOT rely on the existence of the &lt;x/&gt; element on private messages for proper processing.</p>
<example caption='Occupant Sends Private Message'><![CDATA[
<message
from='wiccarocks@shakespeare.lit/laptop'
@ -1910,9 +1929,10 @@
to='coven@chat.shakespeare.lit/firstwitch'
type='chat'>
<body>I'll give thee a wind.</body>
<x xmlns='http://jabber.org/protocol/muc#user' />
</message>
]]></example>
<p>The service is responsible for changing the 'from' address to the sender's occupant JID and delivering the message to the intended recipient's full JID.</p>
<p>The service is responsible for changing the 'from' address to the sender's occupant JID and delivering the message to the intended recipient's full JID. The service SHOULD add the &lt;x/&gt; element if the message does not contain it already.</p>
<example caption='Recipient Receives the Private Message'><![CDATA[
<message
from='coven@chat.shakespeare.lit/firstwitch'
@ -1920,6 +1940,7 @@
to='crone1@shakespeare.lit/desktop'
type='chat'>
<body>I'll give thee a wind.</body>
<x xmlns='http://jabber.org/protocol/muc#user' />
</message>
]]></example>
<p>If the sender attempts to send a private message of type "groupchat" to a particular occupant, the service MUST refuse to deliver the message (since the recipient's client would expect in-room messages to be of type "groupchat") and return a &badrequest; error to the sender:</p>

View File

@ -49,6 +49,18 @@
&stpeter;
&ralphm;
<revision>
<version>1.13.7</version>
<date>2017-08-24</date>
<initials>egp</initials>
<remark><p>Fix examples using invalid XEP-0082 dates.</p></remark>
</revision>
<revision>
<version>1.13.6</version>
<date>2017-06-22</date>
<initials>dg</initials>
<remark><p>Clarify behaviour of publish-options. Fields must be registered</p></remark>
</revision>
<revision>
<version>1.13.5</version>
<date>2016-12-21</date>
@ -951,7 +963,7 @@ And by opposing end them?
<value>hamlet@denmark.lit</value>
</field>
<field var='pubsub#creation_date' label='Creation date' type='text-single'>
<value>2003-07-29T22:56Z</value>
<value>2003-07-29T22:56:10Z</value>
</field>
<field var='pubsub#title' label='A short name for the node' type='text-single'>
<value>Princely Musings (Atom)</value>
@ -2940,11 +2952,11 @@ And by opposing end them?
</pubsub>
</iq>
]]></example>
<p>The &lt;publish-options/&gt; element SHOULD contain a data form (see <cite>XEP-0004</cite>), whose FORM_TYPE SHOULD be "http://jabber.org/protocol/pubsub#publish-options" (see <cite>XEP-0068</cite>).</p>
<p>How the fields are to be handled is up to the the pubsub service, which in the language of XEP-0004 functions as a form-processing entity.</p>
<p>For example, the service may treat the field as a precondition, in which case the service should proceed as follows:</p>
<p>The &lt;publish-options/&gt; element MUST contain a data form (see <cite>XEP-0004</cite>), whose FORM_TYPE MUST be "http://jabber.org/protocol/pubsub#publish-options" (see <cite>XEP-0068</cite>).</p>
<p>Fields and their behaviour MUST be registered with the XMPP Registrar. Each field MUST specify whether it defines METADATA to be attached to the item, a per-item OVERRIDE of the node configuration, or a PRECONDITION to be checked against the node configuration. A pubsub service advertising support for publishing options MUST reject publications with unknown fields.</p>
<p>A field defined as a precondition MUST be processed as follows:</p>
<ol>
<li>If the node exists and the precondition is not met, then the publish shall fail with a &conflict; error condition and a pubsub-specific condition of &lt;precondition-not-met/&gt;.</li>
<li>If the node exists and the precondition is not met, then the publish MUST fail with a &conflict; error condition and a pubsub-specific condition of &lt;precondition-not-met/&gt;.</li>
<li>If the node exists and the precondition is met, then the publish succeeds.</li>
<li>If the node does not exist and the service supports the "auto-create" feature, then the service shall auto-create the node with default configuration in all respects except those specified in the preconditions, and the publish succeeds.</li>
<li>If the node does not exist and the service does not support the "auto-create" feature, then the publish shall fail.</li>
@ -5513,7 +5525,7 @@ And by opposing end them?
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
...
<field var='pubsub#expire'><value>2006-02-28T11:59Z</value></field>
<field var='pubsub#expire'><value>2006-02-28T11:59:59Z</value></field>
...
</x>
</options>
@ -5530,7 +5542,7 @@ And by opposing end them?
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<subscription
expiry='2006-02-28T23:59Z'
expiry='2006-02-28T23:59:59Z'
jid='francisco@denmark.lit'
node='princely_musings'
subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
@ -5579,7 +5591,7 @@ And by opposing end them?
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
...
<field var='pubsub#expire'><value>2006-03-31T23:59Z</value></field>
<field var='pubsub#expire'><value>2006-03-31T23:59:59Z</value></field>
...
</x>
</options>
@ -6782,6 +6794,7 @@ xmpp:pubsub.shakespeare.lit?pubsub;action=retrieve;node=princely_musings
<xs:element name='payload-too-big' type='empty'/>
<xs:element name='payload-required' type='empty'/>
<xs:element name='pending-subscription' type='empty'/>
<xs:element name='precondition-not-met' type='empty'/>
<xs:element name='presence-subscription-required' type='empty'/>
<xs:element name='subid-required' type='empty'/>
<xs:element name='too-many-subscriptions' type='empty'/>

View File

@ -312,18 +312,6 @@
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the Proxy is unable to act as a StreamHost, the Proxy MUST return an error to the Requester, which SHOULD be &notallowed;.</p>
<example caption='Proxy is Unable to Act as a StreamHost'><![CDATA[
<iq from='streamer.example.com'
id='uj2c15z9'
to='requester@example.com/foo'
type='error'>
<error type='auth'>
<forbidden
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the Proxy is unable to act as a StreamHost, the Proxy MUST return an error to the Requester, which SHOULD be &notallowed;.</p>
<example caption='Proxy is Unable to Act as a StreamHost'><![CDATA[

View File

@ -21,6 +21,12 @@
<supersededby/>
<shortname>admin</shortname>
&stpeter;
<revision>
<version>1.2</version>
<date>2017-07-15</date>
<initials>XEP Editor: ssw</initials>
<remark>Fix broken node value in example.</remark>
</revision>
<revision>
<version>1.1</version>
<date>2005-08-19</date>
@ -1613,7 +1619,7 @@
type='set'
xml:lang='en'>
<command xmlns='http://jabber.org/protocol/commands'
node='http://jabber.org/protocol/admin#edit-whitelist'
node='http://jabber.org/protocol/admin#get-online-users-list'
sessionid='get-online-users-list:20040408T0337Z'>
<x xmlns='jabber:x:data' type='submit'>
<field type='hidden' var='FORM_TYPE'>

View File

@ -24,6 +24,23 @@
<shortname>NOT_YET_ASSIGNED</shortname>
&stpeter;
&lance;
<revision>
<version>0.18.3</version>
<date>2017-08-24</date>
<initials>ps</initials>
<remark><p>Make use of &lt;hash-used/&gt; from XEP-0300.</p></remark>
</revision>
<revision>
<version>0.18.2</version>
<date>2017-08-23</date>
<initials>editor (jwi)</initials>
<remark><ul>
<li>Fix a date missing its timezone in examples. (egp)</li>
<li>Remove the mention of UTC, timestamps are already properly described in XEP-0082. (egp)</li>
<li>Add missing length attribute to XML schema. (ps)</li>
<li>Fix incorrect XML in examples. (ps)</li>
</ul></remark>
</revision>
<revision>
<version>0.18.1</version>
<date>2017-05-20</date>
@ -327,7 +344,7 @@
<file>
<media-type>text/plain</media-type>
<name>test.txt</name>
<date>2015-07-26T21:46:00</date>
<date>2015-07-26T21:46:00+01:00</date>
<size>6144</size>
<hash xmlns='urn:xmpp:hashes:2'
algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash>
@ -343,7 +360,7 @@
</tr>
<tr>
<td>date</td>
<td>UTC timestamp specifying the last modified time of the file (which MUST conform to the DateTime profile of &xep0082;).</td>
<td>Timestamp specifying the last modified time of the file (which MUST conform to the DateTime profile of &xep0082;).</td>
<td>OPTIONAL</td>
</tr>
<tr>
@ -354,7 +371,12 @@
<tr>
<td>hash</td>
<td>A hash of the file content, using the &lt;hash/&gt; element defined in &xep0300; and qualifed by the 'urn:xmpp:hashes:2' namespace. Multiple hashes MAY be included for hash agility.</td>
<td>REQUIRED when offering a file, otherwise OPTIONAL</td>
<td>See &lt;hash-used/&gt;</td>
</tr>
<tr>
<td>hash-used</td>
<td>Alternatively to a &lt;hash/&gt; element, the initiator can also include a &lt;hash-used/&gt; element. This avoids the need to read the file twice to calculate the hash.</td>
<td>Either a &lt;hash/&gt; or a &lt;hash-used/&gt; element MUST be included when offering a file.</td>
</tr>
<tr>
<td>media-type</td>
@ -377,7 +399,7 @@
<td>OPTIONAL</td>
</tr>
</table>
<p>One or more &lt;hash/&gt; elements MUST be present when offering a file, but those elements MAY be empty if the hash has not yet been computed. If there is no computed hash value, the &lt;hash/&gt; element(s) MUST possess an 'algo' attribute specifying which hash algorithm will be used. Once a hash has been calculated by the File Sender, the File Sender SHOULD inform the File Receiver of the hash value as described in <link url='#checksum'>Checksum</link>.</p>
<p>One or more &lt;hash/&gt; elements MUST be present when offering a file, but those elements MAY be empty if the hash has not yet been computed. If there is no computed hash value, the &lt;hash/&gt; element(s) MUST possess an 'algo' attribute specifying which hash algorithm will be used. Once a hash has been calculated by the File Sender, the File Sender SHOULD inform the File Receiver of the hash value as described in <link url='#hash'>Checksum</link>.</p>
<p>Additional elements MAY be included as children of the &lt;file/&gt; element to provide additional metadata about the file, such as &xep0264;.</p>
<p>The optional &lt;range/&gt; element MAY possess two attributes:</p>
<table caption='Range Element Attributes'>
@ -750,7 +772,7 @@ a=file-range:<offset>-<(offset + length) | *>]]></code>
<file>
<media-type>text/plain</media-type>
<name>test.txt</name>
<date>2015-07-26T21:46:00</date>
<date>2015-07-26T21:46:00+01:00</date>
<size>6144</size>
<hash xmlns='urn:xmpp:hashes:2'
algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash>
@ -785,7 +807,7 @@ a=file-range:1024-*]]></code>
<section2 topic='Checksum' anchor='hash'>
<p>At any time during the lifetime of the file transfer session, the File Sender can communicate the checksum of the file to the File Receiver.</p>
<p>This can be done in the session-initiate message if the File Sender already knows the checksum, as shown above in Example 3.</p>
<p>After the session-initiate message, this can also be done by sending a session-info message containing a &lt;checksum/&gt; element qualified by the 'urn:xmpp:jingle:apps:file-transfer:5' namespace. The &lt;checksum/&gt; element SHOULD contain 'creator' and 'name' attributes sufficient to identitfy the content the checksum belongs to. Additionally, the &lt;checksum/&gt; element MUST contain a &lt;file/&gt; element which MUST contain at least one &lt;hash/&gt; element qualified by the 'urn:xmpp:hashes:2' namespace. Each &lt;hash/&gt; element contains a checksum of the file data produced in accordance with the hashing function specified by the 'algo' attribute, which MUST be one of the functions listed in the &ianahashes;.</p>
<p>After the session-initiate message, this can also be done by sending a session-info message containing a &lt;checksum/&gt; element qualified by the 'urn:xmpp:jingle:apps:file-transfer:5' namespace. In such a case however, the session-initiate message MUST contain a &lt;hash-used/&gt; element. The &lt;checksum/&gt; element SHOULD contain 'creator' and 'name' attributes sufficient to identitfy the content the checksum belongs to. Additionally, the &lt;checksum/&gt; element MUST contain a &lt;file/&gt; element which MUST contain at least one &lt;hash/&gt; or &lt;hash-used/&gt; element qualified by the 'urn:xmpp:hashes:2' namespace. Each &lt;hash/&gt; element contains a checksum of the file data produced in accordance with the hashing function specified by the 'algo' attribute, which MUST be one of the functions listed in the &ianahashes;.</p>
<example caption="Initiator sends checksum in session-info"><![CDATA[
<iq from='romeo@montague.example/dr4hcr0st3lup4c'
id='kqh401b5'
@ -880,7 +902,7 @@ a=file-range:1024-*]]></code>
<jingle xmlns='urn:xmpp:jingle:1'
action='content-reject'
sid='uj3b2'>
<content creator='initiator' name='requesting-file' senders='initiator'>
<content creator='initiator' name='requesting-file' senders='initiator'/>
<reason>
<failed-application />
<file-not-available xmlns='urn:xmpp:jingle:apps:file-transfer:errors:0' />
@ -904,7 +926,7 @@ a=file-range:1024-*]]></code>
<jingle xmlns='urn:xmpp:jingle:1'
action='content-remove'
sid='uj3b2'>
<content creator='initiator' name='big-file' senders='initiator'>
<content creator='initiator' name='big-file' senders='initiator'/>
<reason>
<media-error />
<file-too-large xmlns='urn:xmpp:jingle:apps:file-transfer:errors:0' />
@ -1054,6 +1076,7 @@ a=file-range:1024-*]]></code>
<xs:complexType name='fileTransferRangeType'>
<xs:attribute name='offset' type='xs:nonNegativeInteger' use='optional' default='0' />
<xs:attribute name='length' type='xs:nonNegativeInteger' use='optional' />
<xs:all xmlns:h='urn:xmpp:hashes:2' minOccurs='0'>
<xs:element ref='h:hash' minOccurs='0' maxOccurs='unbounded' />
</xs:all>
@ -1080,7 +1103,7 @@ a=file-range:1024-*]]></code>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>Thanks to Diana Cionoiu, Olivier Crête, Viktor Fast, Philipp Hancke, Waqas Hussain, Justin Karneges, Steffen Larsen, Yann Leboulanger, Marcus Lundblad, Robert McQueen, Joe Maissel, Glenn Maynard, Ali Sabil, Sjoerd Simons, Will Thompson, Matthew Wild, and Jiří Zárevúcky for their feedback.</p>
<p>Thanks to Diana Cionoiu, Olivier Crête, Viktor Fast, Philipp Hancke, Waqas Hussain, Justin Karneges, Steffen Larsen, Yann Leboulanger, Marcus Lundblad, Robert McQueen, Joe Maissel, Glenn Maynard, Ali Sabil, Sjoerd Simons, Will Thompson, Matthew Wild, Paul Schaub and Jiří Zárevúcky for their feedback.</p>
</section1>
</xep>

View File

@ -3,6 +3,8 @@
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY CHANNEL "&lt;channel/&gt;">
<!ENTITY RELAY "&lt;relay/&gt;">
<!ENTITY STUN "&lt;stun/&gt;">
<!ENTITY TURN "&lt;turn/&gt;">
<!ENTITY SERVICES "&lt;services/&gt;">
<!ENTITY TRACKER "&lt;tracker/&gt;">
%ents;
@ -14,7 +16,7 @@
<abstract>This documents specifies how Jingle Clients can interact with Jingle Relay Nodes Services and how XMPP entities can provide, search and list available Jingle Relay Nodes.</abstract>
&LEGALNOTICE;
<number>0278</number>
<status>Deferred</status>
<status>Experimental</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -32,6 +34,12 @@
<email>thiago@xmppjingle.com</email>
<jid>barata7@gmail.com</jid>
</author>
<revision>
<version>0.3</version>
<date>2017-09-14</date>
<initials>tc</initials>
<remark><p>Added TURN Credentials Service Support.</p></remark>
</revision>
<revision>
<version>0.2</version>
<date>2011-06-21</date>
@ -115,6 +123,7 @@ All signalling, request, response and publishing is done via XMPP, not requiring
<services xmlns='http://jabber.org/protocol/jinglenodes'>
<relay policy='public' address='montague.lit' protocol='udp'/>
<tracker policy='public' address='capulet.lit' protocol='udp'/>
<turn policy='public' address='stun.capulet.lit' protocol='udp'/>
<stun policy='public' address='200.111.111.111' port='3857' protocol='udp'/>
</services>
</iq>
@ -194,6 +203,34 @@ All signalling, request, response and publishing is done via XMPP, not requiring
]]></example>
<p><em>After receiving the &CHANNEL; the requester MUST send his stream to 'host' and 'localport' pair and send a &CANDIDATE; containing the 'host' and 'remoteport' values.</em></p>
</section2>
<section2 topic="Jingle Client Consuming TURN Credentials Service" anchor="clientconsumingturncredentials">
<p>A Jingle Client can request volative TURN credentials, to be used in cases where connectivity check is a requirement. Like, for example, WebRTC. The concept and mechanism is quite similar to the RFC draft <link url='https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00'>REST API For Access To TURN Services'.</link></p>
<p>TURN provides an access control mechanism described in &rfc5389;, where long-term credentials are provided as part of the TURN protocol. Therefore the credentials provided in this Jingle Nodes mechanism are time-limited, but SHOULD be used as long-term credentials, when authentication against a TURN Server.
</p>
<p>
<em>Note: There is no need to run TURN server or support within a Jingle Relay. This mechanism allows decoupled deployment of distributed TURN Servers, without the requirement of database based authentication. </em>
</p>
<example caption="TURN Credentials request"><![CDATA[
<iq from='romeo@montague.lit/orchard'
id='uw72g176'
to='juliet@capulet.lit/balcony'
type='get'>
<turn xmlns='http://jabber.org/protocol/jinglenodes#turncredentials' protocol='udp'/>
</iq>
]]></example>
<example caption="TUNR Credentials Returned by the service"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
id='uw72g176'
to='romeo@montague.lit/orchard'
type='result'>
<turn ttl='60000'
uri='turn:200.20.2.10:1984?transport=udp'
username='1433895918506:romeocapulet'
password='1Dj9XZ5fwvKS6YoQZOoORcFnXaI='
/>
</iq>
]]></example>
</section2>
</section1>
<section1 topic="Services Definitions" anchor="servicesdefinition">
<section2 topic="Relay Channel Service" anchor="relaychannelservice">
@ -293,7 +330,7 @@ All signalling, request, response and publishing is done via XMPP, not requiring
</section3>
</section2>
<section2 topic="Services Element" anchor="def-services">
<p>The &SERVICES; element MAY be empty or contain &RELAY; and/or &TRACKER; elements.</p>
<p>The &SERVICES; element MAY be empty or contain &RELAY;, &STUN; and/or &TRACKER; elements.</p>
<p>The attributes of the &RELAY; and &TRACKER; element are as follows.</p>
<table caption="Attributes of Relay and Tracker Elements">
<tr>
@ -323,6 +360,48 @@ All signalling, request, response and publishing is done via XMPP, not requiring
</tr>
</table>
</section2>
<section2 topic="TURN Credentials Service Element" anchor="def-turn-credentials">
<p>The attributes of the &TURN; element are as follows.</p>
<table caption="Attributes of TURN Elements">
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>ttl</td>
<td>The duration in seconds for which the provided credentials are valid.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>uri</td>
<td>The TURN Server URI.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>username</td>
<td>The username to be used on TURN authentication. THe recommended format is a colon-delimited concatenation of expiration timestamp and the requester bare JID.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>password</td>
<td>The ppassword to be used on TURN authentication. Is the result of 'base64(hmac(secret_key, username))'. Where 'secret_key' is shared between the TURN server and entity providing the credentials.</td>
<td>REQUIRED</td>
</tr>
</table>
<section3 topic="Ttl Attribute" anchor="def-ttlattribute">
<p>The duration in seconds for which the provided credentials are valid. The usual and recommended value is 86400 seconds (one day).</p>
</section3>
<section3 topic="URI Attribute" anchor="def-uriattribute">
<p>The TURN Server URI as described in <link url="https://tools.ietf.org/html/draft-petithuguenin-behave-turn-uris-03">I-D.petithuguenin-behave-turn-uris</link></p>
</section3>
<section3 topic="Username Attribute" anchor="def-ttlattribute">
<p>WebRTC's TURN request uses the 'username' value for its USERNAME and PASSWORD attributes, for the input to the MESSAGE-INTEGRITY hash.</p>
</section3>
<section3 topic="Password Attribute" anchor="def-ttlattribute">
<p>Along with 'username', WebRTC's TURN request uses the 'password' value for its USERNAME and PASSWORD attributes, for the input to the MESSAGE-INTEGRITY hash.</p>
</section3>
</section2>
</section1>
<section1 topic="Determining Support" anchor="support">
<p>To advertise its support for the Jingle Nodes support, when replying to &xep0030; information requests an entity MUST return URNs for any version of this protocol that the entity supports -- e.g., "http://jabber.org/protocol/jinglenodes" for this version&VNOTE;.</p>
@ -342,8 +421,9 @@ All signalling, request, response and publishing is done via XMPP, not requiring
to='romeo@montague.lit/orchard'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<feature var='http://jabber.org/protocol/jinglenodes'/>
<feature var='http://jabber.org/protocol/jinglenodes#channel'/>
<feature var='http://jabber.org/protocol/jinglenodes'/>
<feature var='http://jabber.org/protocol/jinglenodes#channel'/>
<feature var='http://jabber.org/protocol/jinglenodes#turncredentials'/>
</query>
</iq>
]]></example>
@ -356,6 +436,10 @@ All signalling, request, response and publishing is done via XMPP, not requiring
<em>Note: This use case is also similar to a Jingle to SIP Interoperability Service.</em>
</p>
</section2>
<section2 topic="Jingle Client that uses WebRTC with TURN required" anchor="webrtcturn">
<p>A Jingle Client that uses WebRTC, therefore requiring a TURN Server and its credentials to successfully alocate channels. This specification describes a simple way of discovering TURN Services and retrieving credentials to successfully allocate channels.
This also simplifies deployment and distribution of TURN servers, since its stateless authentication does not require connectivity to database authoriztion services.</p>
</section2>
<section2 topic="Jingle Client with ICE-UDP Transport with STUN support but no TURN support" anchor="iceudpnoturn">
<p>A Jingle Client with STUN support but no TURN support can use Relay Node Services as the fallback candidate instead of a TURN candidate. For instance, after a connectivity check proccess, none of the direct candidates worked. The Client can use the Relay Node Candidate as the fallback candidate(the lowest priority candidate).</p>
</section2>
@ -420,6 +504,13 @@ All signalling, request, response and publishing is done via XMPP, not requiring
<xs:attribute name='expire' type='xs:string' use='required'/>
</xs:element>
<xs:element name='turn'>
<xs:attribute name='ttl' type='xs:string' use='required'/>
<xs:attribute name='uri' type='xs:string' use='required'/>
<xs:attribute name='username' type='xs:string' use='required'/>
<xs:attribute name='password' type='xs:string' use='required'/>
</xs:element>
<xs:element name='services'>
<xs:complexType>
<xs:sequence>
@ -435,6 +526,10 @@ All signalling, request, response and publishing is done via XMPP, not requiring
type='serviceElementType'
minOccurs='0'
maxOccurs='unbounded'/>
<xs:element name='turn'
type='serviceElementType'
minOccurs='0'
maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -2,11 +2,13 @@
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY nokia11 "<note>LTE Smartphone measurements &lt;<link url='https://web.archive.org/web/20160624043050/http://networks.nokia.com/system/files/document/lte_measurements_final.pdf'>http://networks.nokia.com/system/files/document/lte_measurements_final.pdf</link>&gt;</note>">
<!ENTITY huang12 "<note>A Close Examination of Performance and Power Characteristics of 4G LTE Networks &lt;<link url='https://doi.org/10.1145/2307636.2307658'>doi:2307636.2307658</link>&gt;</note>">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Mobile Considerations</title>
<title>Mobile Considerations on LTE Networks</title>
<abstract>
This document provides background information for XMPP implementors
concerned with mobile devices operating on an LTE cellular network.
@ -30,6 +32,17 @@
<jid>dave.cridland@isode.com</jid>
</author>
&sam;
<revision>
<version>0.4.1</version>
<date>2017-09-17</date>
<initials>ssw</initials>
<remark>
<ul>
<li>Minor editorial fixes.</li>
<li>Remove reference to EXI which has no implementations.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.4.0</version>
<date>2017-01-17</date>
@ -103,17 +116,17 @@
Compression of XMPP data can be achieved with the DEFLATE algorithm
(&rfc1951;) via TLS compression (&rfc3749;) or &xep0138; (which also
supports other compression algorithms).
While the security implications of stream compression are beyond the scope
of this document (See the aforementioned RFC or XEP for more info), the
author does not recommend using TLS compression with XMPP (or in general).
A description of the security implications of stream compression is beyond
the scope of this document (See &rfc3749; or &xep0138; for more
information), but the author does not recommend using TLS compression with
XMPP (or in general).
If compression must be used, stream level compression should be
implemented instead, and the compressed stream should have a full flush
performed on stanza boundaries to help prevent a class of chosen plaintext
attacks which can cause data leakage in compressed streams.
performed on stanza boundaries to help prevent chosen plaintext attacks.
While this may mitigate some of the benefits of compression by raising
compression ratios, in a large, real world deployment at HipChat, network
traffic was still observed to decrease by a factor of 0.58 when enabling
&xep0138; with ZLIB compression!
compression ratios, in a large, real world deployment, network traffic was
still observed to decrease by a factor of 0.58 when enabling &xep0138;
with ZLIB compression.
</p>
<p>
While the CPU cost of compression may directly translate to higher power
@ -122,13 +135,10 @@
power per bit than 3G networks as will be seen later in this document.
However, CPU usage is also not guaranteed to rise due to compression.
In the aforementioned deployment of stream compression, a
<em>decrease</em> in CPU utilization by a factor of 0.60 was observed due
to the fact that there were fewer packets that needed to be handled by the
OS (which also takes CPU time), and, potentially more importantly, less
data that needed to be TLS-encrypted (which is a much more CPU-expensive
operation than compression).
<em>decrease</em> in CPU utilization by a factor of 0.60 was observed,
presumably due to reductions in TLS and packet handling overhead.
Therefore CPU time spent on compression (for ZLIB, at least; other
algorithms were not tested) should be considered negligable.
algorithms were not tested) can be considered negligable.
</p>
<p>
Supporting compression and performming a full flush on stanza boundaries
@ -140,12 +150,10 @@
While the wide spread adoption of LTE has dramatically increased available
bandwidth on mobile devices, it has also increased power consumption.
According to one study, early LTE devices consumed 5&#x2013;20% more power
than their 3G counterparts
<note>LTE Smartphone measurements &lt;<link url='http://networks.nokia.com/system/files/document/lte_measurements_final.pdf'>http://networks.nokia.com/system/files/document/lte_measurements_final.pdf</link>&gt;</note>.
than their 3G counterparts &nokia11;.
On some networks that support the legacy SVLTE (Simultaneous Voice and
LTE) instead of the more modern VoLTE (Voice Over LTE) standard, or even
CSFB (Circuit-switched fallback) this number would (presumably) be even
higher.
LTE) or CSFB (Circuit-switched fallback) instead of the more modern VoLTE
(Voice Over LTE) standard, this number would (presumably) be even higher.
</p>
<p>
XMPP server and client implementers, bearing this increased power usage in
@ -153,12 +161,11 @@
traffic to minimize network usage.
For the downlink, LTE user equipment
(UE) utilizes Orthogonal Frequency Division Multiplexing (OFDM), which is
somewhat inefficient
<note>A Close Examination of Performance and Power Characteristics of 4G LTE Networks &lt;<link url='http://www.cs.columbia.edu/~lierranli/coms6998-7Spring2014/papers/rrclte_mobisys2012.pdf'>http://www.cs.columbia.edu/~lierranli/coms6998-7Spring2014/papers/rrclte_mobisys2012.pdf</link>&gt;</note>.
somewhat inefficient &huang12;.
On the uplink side a different technology, Single-carrier frequency
division multiple access (SC-FDMA) is used, which is slightly more
efficient than traditional (non linearly-precoded) OFDM, slightly
offsetting the fact that broadcasting requires more power than receiving.
efficient than traditional OFDM, slightly offsetting the fact that
broadcasting requires more power than receiving.
LTE UE also implements a Discontinuous reception (DRX) mode in which the
hardware can sleep until it is woken by a paging message or is needed to
perform some task.
@ -182,14 +189,14 @@
prevent the server from closing the socket.
</p>
</section2>
<section2 topic='Transmit as much data as you can at once'>
<section2 topic='When transmitting, transmit as much as you can'>
<p>
If one is on 3G, transmitting a small amount of data will cause the
radio to enter FACH mode which is significantly cheaper than its high
power mode.
On LTE radios, however, transmitting small amounts of data is vastly
more expensive per bit due to the higher tail-times (the time it takes
for the radio to change state).
more expensive per bit due to the higher tail-time (the time it takes
for the radio to change state) of approximately 11 seconds&huang12;.
On LTE radios, one should transmit as much data from the client as
possible when the radio is already on (eg. by placing messages in a send
queue and executing the queue as a batch when the radio is on).
@ -199,10 +206,8 @@
</p>
<p>
These rules also apply to server operators: If the server receives data,
the phones radio is already on therefore you should send any pending
data.
Batching data to be sent and sending it all at once will help reduce
power consumption.
the phones radio is already on, therefore you should flush any pending
data as soon as possible after receiving data from a client.
</p>
</section2>
</section1>
@ -213,7 +218,6 @@
optimizations for them in servers.
</p>
<p>&xep0138; provides stream level compression.</p>
<p>&xep0322; allows XMPP streams to use the EXI XML format.</p>
<p>
&xep0115; provides a mechanism for caching, and hence eliding, the
disco#info requests needed to negotiate optional features.
@ -247,8 +251,8 @@
<p>
This XEP was originally written by Dave Cridland, and parts of his
original work were used in this rewrite.
Thanks to Atlassian for allowing me to release hard numbers from their
XMPP compression deployment.
Thanks to Atlassian (HipChat) for allowing me to release numbers from
their XMPP compression deployment.
</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>

View File

@ -25,11 +25,17 @@
&ksmith;
&tobias;
<revision>
<version>0.5.2</version>
<date>2017-08-20</date>
<version>0.5.3</version>
<date>2017-10-04</date>
<initials>fs</initials>
<remark><p>Clarify textual content of the &lt;hash/&gt; element.</p></remark>
</revision>
<revision>
<version>0.5.2</version>
<date>2017-08-21</date>
<initials>ps</initials>
<remark><p>Add hash-used element</p></remark>
</revision>
<revision>
<version>0.5.1</version>
<date>2017-03-17</date>
@ -99,6 +105,8 @@
<p>An XMPP protocol can include more than one instance of the &lt;hash/&gt; element, as long as each one has a different value for the 'algo' attribute:</p>
<code><![CDATA[<hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>2AfMGH8O7UNPTvUVAM9aK13mpCY=</hash>
<hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=</hash>]]></code>
<p>In certain scenarios it makes sense to communicate the hash algorithm that is used prior to the calculation of the hash value.</p>
<code><![CDATA[<hash-used xmlns='urn:xmpp:hashes:2' algo='sha-256'/>]]></code>
<p>The value of the 'algo' attribute MUST be one of the values from the &ianahashes; maintained by &IANA;, or one of the values
defined in the following table.</p>
<table caption='Additional Hash Function Textual Names'>
@ -399,13 +407,21 @@
</xs:complexType>
</xs:element>
<xs:element name='hash-used'>
<xs:complexType>
<xs:extension base='empty'>
<xs:attribute name='algo' type='xs:NCName' use='required'/>
</xs:extension>
</xs:complexType>
</xs:element>
</xs:schema>
]]></code>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>Thanks to Dave Cridland, Waqas Hussain, Glenn Maynard, Remko
Tronçon, Christian Schudt, and Florian Schmaus for their input.</p>
Tronçon, Paul Schaub, Christian Schudt, and Florian Schmaus for their input.</p>
</section1>
</xep>

View File

@ -24,6 +24,18 @@
<supersededby/>
<shortname>idle</shortname>
&tobias;
<revision>
<version>1.0.2</version>
<date>2017-07-17</date>
<initials>egp</initials>
<remark><p>Make the schema more precise about a date being a xs:dateTime.</p></remark>
</revision>
<revision>
<version>1.0.1</version>
<date>2017-05-30</date>
<initials>egp</initials>
<remark><p>Be precise about the &xep0082; profile used.</p></remark>
</revision>
<revision>
<version>1.0</version>
<date>2015-04-02</date>
@ -51,7 +63,7 @@
</header>
<section1 topic='Introduction' anchor='intro'>
<p>This protocol describes a way to communicate a user's last interaction time with other XMPP entities over &PRESENCE; stanzas. For the purposes of this document, user interaction here refers to a human end user interacting with her device by means of a keyboard, mouse, touch screen, and so on. Based on this information XMPP clients can display the time a contact went idle or a duration for how long a contact has been idle, thereby allowing end users to estimate the expected responsiveness of their contacts.</p>
<p>This protocol uses absolute timestamps formatted according to &xep0082;, indicated as value of the 'since' attribute in the &lt;idle/&gt; element.</p>
<p>This protocol uses absolute timestamps formatted according to the DateTime profile of &xep0082;, indicated as value of the 'since' attribute in the &lt;idle/&gt; element.</p>
<p>Experience has shown a number of issues with &xep0256;:</p>
<ul>
<li>The use of relative durations is too vague. It requires additional information from &xep0203; to provide a reliable user experience.</li>
@ -98,7 +110,7 @@
<xs:element name="idle">
<xs:complexType>
<xs:attribute name="since" use="required" type="xs:string"/>
<xs:attribute name="since" use="required" type="xs:dateTime"/>
</xs:complexType>
</xs:element>

View File

@ -55,16 +55,16 @@
<p>This document addresses the following requirements:</p>
<ol>
<li>Make it possible for remote services or entities to manage user's roster by the same mechanisms that descibed in the &rfc6121;.</li>
<li>Provide a way for user to control which services have permission to manage his roster.</li>
<li>Provide a way for users to control which services have permission to manage their roster.</li>
</ol>
</section1>
<section1 topic='Glossary' anchor='glossary'>
<ul>
<li><strong>Remote entity</strong> — the entity that wants to modify user's roster.</li>
<li><strong>User</strong> — the entity which roster the remote entity wants to have access to.</li>
<li><strong>User's server</strong> — the XMPP server User connected to.</li>
<li><strong>Roster</strong> — the list of User's contacts as defined in the &rfc6121;.</li>
</ul>
<dl>
<di><dt>Remote entity</dt><dd>the entity that wants to modify user's roster.</dd></di>
<di><dt>User</dt><dd>the entity which roster the remote entity wants to have access to.</dd></di>
<di><dt>User's server</dt><dd>the XMPP server User connected to.</dd></di>
<di><dt>Roster</dt><dd>the list of User's contacts as defined in the &rfc6121;.</dd></di>
</dl>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic='Remote entity asks for permission to manage user&apos;s roster' anchor='ask_permission'>
@ -82,7 +82,7 @@
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>You must have a presence subscription to be able to request remote roster management service.</text>
</error>
</iq>]]></example>
<p>The user's server SHOULD then generate a form request using &xep0004; to client in order to ask user if he's OK with granting the permission to the remote entity. The "challenge" form field is generated by the server and is used to identify the client's response. The server also MUST immediatly answer to the request IQ.</p>
<p>The user's server SHOULD then generate a form request using &xep0004; to client in order to ask user if they are OK with granting the permission to the remote entity. The "challenge" form field is generated by the server and is used to identify the client's response. The server also MUST immediatly answer to the request IQ.</p>
<p>NOTE: if the entity is already granted with the permission, the server SHOULD immediatly answer with a success response and skip querying the user.</p>
<example caption='Server asks user for the permission'><![CDATA[
<message from='example.com'
@ -220,7 +220,7 @@
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>You have tried to modify the item you don't allowed to.</text>
</iq>]]></example>
</section2>
<section2 topic='Client requests list of components with permissions to edit his roster'>
<section2 topic='Client requests list of components with permissions to edit their roster'>
<p>User can ask the server to provide a list of components or servers which have permissions to edit their roster.</p>
<example caption='User asks the server to get list of components which can edit their roster'><![CDATA[
<iq from='juliet@example.com/home' to='icq.example.com' type='get' id='roster_5'>

View File

@ -10,7 +10,7 @@
<abstract>This specification defines an XMPP protocol extension for the third-party control of telephone calls and other similar media sessions. The protocol includes support for session management/signaling, as well as advanced media resources such as speech recognizers, speech synthesizers and audio/video recorders. The protocol serves a different purpose from that of first-party protocols such as Jingle or SIP, and is compatible with those protocols.</abstract>
&LEGALNOTICE;
<number>0327</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -34,6 +34,12 @@
<jid>jdecastro@tropo.com</jid>
<uri>http://tropo.com</uri>
</author>
<revision>
<version>0.8</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.7</version>
<date>2015-07-15</date>

View File

@ -10,7 +10,7 @@
<abstract>This document specifies a simple extension to existing protocols that allows an entity to request information about files.</abstract>
&LEGALNOTICE;
<number>0329</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -32,6 +32,12 @@
<jid>j.lagrange@jabber.org</jid>
</author>
&lance;
<revision>
<version>0.4</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.3</version>
<date>2016-08-07</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification defines how XMPP can be used to transport HTTP communication over peer-to-peer networks.</abstract>
&LEGALNOTICE;
<number>0332</number>
<status>Experimental</status>
<status>Deferred</status>
<lastcall>2014-10-21</lastcall>
<type>Standards Track</type>
<sig>Standards</sig>
@ -28,6 +28,12 @@
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
&peterwaher;
<revision>
<version>0.5</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.4</version>
<date>2015-11-09</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification describes a solution of marking the last received, displayed and acknowledged message in a chat.</abstract>
&LEGALNOTICE;
<number>0333</number>
<status>Experimental</status>
<status>Deferred</status>
<lastcall>2017-03-01</lastcall>
<lastcall>2017-02-22</lastcall>
<lastcall>2017-02-11</lastcall>
@ -30,6 +30,12 @@
<email>im@spencermacdonald.com</email>
<jid>im@spencermacdonald.com</jid>
</author>
<revision>
<version>0.3</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.2.1</version>
<date>2015-10-28</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification provides a common framework for sending events to event logs over XMPP networks.</abstract>
&LEGALNOTICE;
<number>0337</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -22,6 +22,12 @@
<supersededby/>
<shortname>eventlogging</shortname>
&peterwaher;
<revision>
<version>0.3</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.2</version>
<date>2015-11-09</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification provides an XML mapping for translating the RFC 5888 SDP Grouping Framework to Jingle</abstract>
&LEGALNOTICE;
<number>0338</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -21,6 +21,12 @@
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
&fippo;
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-01-08</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification provides an XML mapping for translating the RFC 5766 Source-Specific Media Attributes from SDP to Jingle</abstract>
&LEGALNOTICE;
<number>0339</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -21,6 +21,12 @@
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
&fippo;
<revision>
<version>0.3</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.2</version>
<date>2015-11-09</date>

View File

@ -14,7 +14,7 @@
</abstract>
&LEGALNOTICE;
<number>0340</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -40,6 +40,12 @@
<jid>lubo@sip-communicator.org</jid>
</author>
&fippo;
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-01-08</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification defines an extension to the Rayo protocol (XEP-0327) to provide provision for performing Call Progress Analysis on a call under the control of a Rayo client.</abstract>
&LEGALNOTICE;
<number>0341</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -28,6 +28,12 @@
<jid>ben@langfeld.me</jid>
<uri>http://langfeld.me</uri>
</author>
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-01-14</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification defines an extension to the Rayo protocol (XEP-0327) to provide provision for sending and receiving faxcimilies via a call under the control of a Rayo client.</abstract>
&LEGALNOTICE;
<number>0342</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -29,6 +29,12 @@
<jid>ben@langfeld.me</jid>
<uri>http://langfeld.me</uri>
</author>
<revision>
<version>0.3</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.2</version>
<date>2014-03-13</date>

View File

@ -15,7 +15,7 @@
<abstract>This specification defines how to use the ICE-UDP Jingle transport method to send media data using WebRTC DataChannels, so technically uses DTLS/SCTP on top of the Interactive Connectivity Establishment (ICE) methodology, which provides robust NAT traversal for media traffic.</abstract>
&LEGALNOTICE;
<number>0343</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -31,6 +31,12 @@
<surname>Bavendiek</surname>
<email>bavendiek@dbis.rwth-aachen.de</email>
</author>
<revision>
<version>0.3</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.2</version>
<date>2014-07-15</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification provides documentation how Server Dialback is used together with Transport Layer Security, and discusses how the security considerations of Dialback are changed by the introduction of TLS and/or DNSSEC.</abstract>
&LEGALNOTICE;
<number>0344</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -23,6 +23,12 @@
<shortname>N/A</shortname>
&fippo;
&dcridland;
<revision>
<version>0.4</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.3</version>
<date>2015-03-23</date>

View File

@ -13,7 +13,7 @@
</abstract>
&LEGALNOTICE;
<number>0345</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Procedural</type>
<sig>None</sig>
<approver>Board</approver>
@ -22,6 +22,12 @@
<supersededby/>
<shortname>N/A</shortname>
&dcridland;
<revision>
<version>0.4</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.3</version>
<date>2014-08-04</date>

View File

@ -12,7 +12,7 @@
<abstract>This specification describes a series of conventions that allow the management of form templates and publishing of completed forms.</abstract>
&LEGALNOTICE;
<number>0346</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -27,6 +27,12 @@
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
&ksmithisode;
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-04-10</date>

View File

@ -14,7 +14,7 @@
<abstract>This specification describes an architecture based on the XMPP protocol whereby Things can be installed and safely discovered by their owners and connected into networks of Things.</abstract>
&LEGALNOTICE;
<number>0347</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -41,6 +41,12 @@
<jid>TBD</jid>
<uri>http://www-rnks.informatik.tu-cottbus.de/~rklauck</uri>
</author>
<revision>
<version>0.5</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.4.1</version>
<date>2016-08-20</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification describes a method whereby a client can sign a form using credentials not related to the current connection.</abstract>
&LEGALNOTICE;
<number>0348</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -25,6 +25,12 @@
<supersededby/>
<shortname>signing-forms</shortname>
&peterwaher;
<revision>
<version>0.3</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.2</version>
<date>2015-11-09</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification describes an extension to the Rayo protocol to support clustering of Rayo servers and their presentation as a unified service.</abstract>
&LEGALNOTICE;
<number>0349</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -34,6 +34,12 @@
<email>mperez@tropo.com</email>
<uri>http://tropo.com</uri>
</author>
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-06-18</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification defines an XMPP protocol extension for including geolocation data in XEP-0004 data forms.</abstract>
&LEGALNOTICE;
<number>0350</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<dependencies>
@ -31,6 +31,12 @@
<email>laukner@gmail.com</email>
<jid>laukner@jabber.org</jid>
</author>
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-07-03</date>

View File

@ -10,7 +10,7 @@
<abstract>This specification defines a modern efficient way to deliver PubSub notifications.</abstract>
&LEGALNOTICE;
<number>0351</number>
<status>Experimental</status>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
@ -29,6 +29,12 @@
<email>Binary@JRuDevels.org</email>
<jid>Binary@JRuDevels.org</jid>
</author>
<revision>
<version>0.2</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2014-08-28</date>

View File

@ -10,7 +10,7 @@
<abstract>This document defines a way for the client to indicate its active/inactive state.</abstract>
&LEGALNOTICE;
<number>0352</number>
<status>Proposed</status>
<status>Experimental</status>
<lastcall>2017-03-28</lastcall>
<lastcall>2017-03-01</lastcall>
<lastcall>2017-02-22</lastcall>
@ -25,6 +25,12 @@
<supersededby/>
<shortname>csi</shortname>
&mwild;
<revision>
<version>0.2.1</version>
<date>2017-02-18</date>
<initials>fs</initials>
<remark><p>Clarify that the CSI state is not restored when the stream is resumed.</p></remark>
</revision>
<revision>
<version>0.2</version>
<date>2015-10-02</date>
@ -148,6 +154,14 @@ and responds to the ping with a pong -->
<iq to='juliet@capulet.lit/baclony' from='capulet.lit' id='ping1' type='result'/>
<!-- Stream state is now 'active' -->]]></example>
</section2>
<section2 topic='Interaction with Stream Resumption' anchor='stream-resumption'>
<p>After a previous stream was resumed using mechanisms like
&xep0198;, the CSI state is <em>not</em> restored. That is, stream
resumption does not affect the current CSI state, which always
defaults to 'active' for new and resumed streams. Clients wishing
to immediately go to the inactive state should do so after stream
resumption.</p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>To protect the privacy of users, servers MUST NOT reveal the clients active/inactive state to other
@ -182,4 +196,7 @@ and responds to the ping with a pong -->
</xs:schema>
]]></code>
</section1>
<section1 topic='Acknowledgements' anchor='acknowledgements'>
<p>Thanks to Florian Schmaus for his feedback.</p>
</section1>
</xep>

Some files were not shown because too many files have changed in this diff Show More