Merge branch 'premerge' into main

This commit is contained in:
Jonas Schäfer 2021-01-19 18:20:47 +01:00
commit ac1989bad5
3 changed files with 330 additions and 37 deletions

View File

@ -0,0 +1,272 @@
<?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>Service Outage Status</title>
<abstract>This document defines an XMPP protocol extension that enables a server to communicate issues with the server to all users in a semantic manner.</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-0060</spec>
<spec>XEP-0128</spec>
<spec>XEP-0222</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<author>
<firstname>Mathieu</firstname>
<surname>Pasquet</surname>
<email>mathieui@mathieui.net</email>
<jid>mathieui@mathieui.net</jid>
</author>
<revision>
<version>0.0.1</version>
<date>2021-01-18</date>
<initials>mp</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>The XMPP Network is a network of servers which each have their own administration policies, status reports, and other peculiarities. &xep0157; provides a consistent framework for reaching out to administrators and reporting abuse, incidents, or even giving feedback on the service, and the goal of this specification is to provide a similar framework for letting users (or other entities) know the server status in-band or out of band (in case of hard failures).</p>
<p>Centralized systems usually control both the infrastructure and client code, making it easy to hardcode information retrieval one way or the other.</p>
<p>The usual way of informing users of planned maintenance, partial or total outage was previously through "announce" modules that lets the admin broadcast server-wided messages. This approach has several drawbacks, as it will appear in most clients as a new discussion with the server JID, which can prove confusing. It also does not provide a way to reach the user when the XMPP server is offline.</p>
<p>This XEP provides:</p>
<ul>
<li>An informational way of exposing an external service endpoint containing machine-readable data using &xep0128;</li>
<li>A specification of the data this service should provide</li>
<li>A normative way of providing such information in-band, when the outage is not complete</li>
<li>A way to reference and archive such incidents, in a &xep0060; node</li>
</ul>
</section1>
<section1 topic='External endpoint discovery' anchor='external-disco'>
<p>To make such discovery possible, we specify a &xep0128; mechanism that a server SHOULD return in response to service discovery information ("disco#info") requests sent to the bare domain of the server. This information MUST be scoped using a FORM_TYPE of "urn:xmpp:tmp:sos" (as already specified in <cite>XEP-0128</cite>) and data form fields registered for this purpose as defined in the <link url='#registrar'>XMPP Registrar Considerations</link> section of this document.</p>
<p>Values of 'external-status-addresses' form field MUST be valid URIs, i.e. comply with the 'xs:anyURI' datatype of &w3xmlschema2;.</p>
<example caption='Entity queries server for information'><![CDATA[
<iq from='thirdwitch@shakespeare.lit/chamber'
to='shakespeare.lit'
id='disco1'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption='Server communicates information'><![CDATA[
<iq from='shakespeare.lit'
to='thirdwitch@shakespeare.list/chamber'
id='disco1'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity category='server' type='im'/>
<feature var='http://jabber.org/protocol/disco'/>
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>urn:xmpp:tmp:sos</value>
</field>
<field var='external-status-addresses'>
<value>http://secondary.shakespeare.lit/status.json</value>
</field>
</x>
</query>
</iq>
]]></example>
<p>Links present inside the 'external-status-addresses' field SHOULD use HTTP/HTTPS protocol and the resources referenced MUST be available without authentication.</p>
</section1>
<section1 topic='External status format' anchor='json-schema'>
<p>TODO: do we want this to be XML or json? I have no real preference, in any case it should be preferably generated by a tool but easy to write by hand, as this needs to be usable in situations where time is the essence.</p>
<p>The format used for the external status is defined here, to allow a wide range
of compatibility across services and clients.</p>
<p>A client MUST ignore unknown extra fields present in the JSON file, to allow extensibility, and implementations MAY add other fields.</p>
<example caption='Example status'><![CDATA[
{
"outage": "complete",
"planned": true,
"beginning": "2021-01-12T01:01:01Z",
"expected_end": "2021-01-12T05:00:00Z",
"message": {
"default": "Mise à jour du serveur",
"en": "The serveur is being updated"
}
}
]]></example>
<p>The "message" field MUST contain at least a message on the "default" key, that will be
used by the client if the current user language is not found. It is left to the
operator to determine which language is more relevant as a default, according to the
servers user base.</p>
<p>The following JSON schema is provided as a means to describe and validate the
file exposed by the external service:</p>
<code><![CDATA[
{
"$id": "http://xmpp.org/server-outage-schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "XMPP Server Outage Format",
"type": "object",
"required": ["beginning"],
"additionalProperties": true,
"properties": {
"outage": {
"type": "string",
"enum": ["partial", "complete"],
"description": "The outage status (partial or complete)."
},
"planned": {
"type": "boolean",
"description": "If the outage was planned or not."
},
"beginning": {
"type": "string",
"format": "date-time",
"description": "Approximate time of the start of the outage."
},
"expected_end": {
"type": "string",
"format": "date-time",
"description": "Estimated time of the end of the outage (if known)."
},
"message": {
"type": "object",
"description": "Textual message to service users, each key being 'defaul' or a BCP47 language tag.",
"required": ["default"],
"properties": {
"default": { "type": "string"}
},
"patternProperties": {
"default": {"type": "string"},
".*": {"type": "string"}
}
}
}
}
]]></code>
</section1>
<section1 topic="Pubsub Node" anchor="pubsubnode">
<p>For in-band notifications of server issues, a service MUST expose a pubsub node with the acess model defined in &xep0222;.
This pubsub node contains items describing outages, and each item MUST have an 'id' attribute value containing
the publishing time, in &xep0082; format.</p>
<p>Clients implementing this extension SHOULD subscribe to the '+notify' on that node, as defined in &xep0060;.</p>
<p>Entities from other servers MAY be allowed to subscribe to other server nodes, to allow an external service
to monitor the server. Doing so allows aggregation of XMPP outage events across the network, for a better
transparency.</p>
<example caption='Server operator publishes an outage event'><![CDATA[
<iq from='firstwitch@shakespeare.lit/broom' to='shakespeare.lit' type='set' id='pub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:tmp:sos'>
<item id="2021-01-01T01:01:01Z">
<outage xmlns='urn:xmpp:tmp:sos'>
<description xml:lang='en'>The ICQ and MSN gateways are down</description>
<description xml:lang='fr'>Les passerelles ICQ et MSN sont mortes</description>
<planned>false</planned>
<expected_end>2021-01-01T05:00:00Z</expected_end>
</outage>
</item>
</publish>
</pubsub>
</iq>
]]></example>
<example caption='Client subscribed receives an outage event'><![CDATA[
<message from='shakespeare.lit'
to='macbeth@shakespeare.lit/throne'
type='headline'
id='outagefoo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='urn:xmpp:tmp:sos'>
<item id="2021-01-01T01:01:01Z">
<outage xmlns='urn:xmpp:tmp:sos'>
<description xml:lang='en'>The ICQ and MSN gateways are down</description>
<description xml:lang='fr'>Les passerelles ICQ et MSN sont mortes</description>
<planned>false</planned>
<expected_end>2021-01-01T05:00:00Z</expected_end>
</outage>
</item>
</items>
</event>
</message>
]]></example>
<p>When the outage is over, servers operators SHOULD publish an &lt;outage-end/&gt; element
with the item id matching the time at which the issue was resolved. It can optionally
contain a description.</p>
<example caption='Server operator publishes an end of outage event'><![CDATA[
<iq from='firstwitch@shakespeare.lit/broom' to='shakespeare.lit' type='set' id='pub2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:tmp:sos'>
<item id="2021-01-01T02:05:01Z">
<outage-end xmlns='urn:xmpp:tmp:sos'>
<description xml:lang="en">Everything has been fixed!</description>
<description xml:lang="fr">Tout a été corrigé!</description>
</outage-end>
</item>
</publish>
</pubsub>
</iq>
]]></example>
<p>Clients receiving this notification SHOULD remove the information about the outage from the users view, and MAY
display the new message briefly.</p>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<p>This extension has been thought for several different cases of service outages:</p>
<ul>
<li>A client failing to connect to a server is able to display an informative message to the user if the server is having issues.</li>
<li>A server experiencing difficulties is able to communicate it to the users, and clients can display the information prominently.</li>
<li>An external service can keep track of the various outages, either for a single server or a number of them, and present the information in a structured manner.</li>
</ul>
</section1>
<section1 topic='Business Rules' anchor='rules'>
<p>A client implementing this extension MUST fetch the addresses of the external service and cache it
for a reasonable amount of time (several days), to be able to use it when an issue occurs</p>
</section1>
<section1 topic='Internationalization Considerations' anchor='i18n'>
<p>Both the JSON and the XML format defined in this document allow for internationalization in the fields that are expected to be presented to the user as-is. The other fields are machine-readable and their various values SHOULD be translated in the implementing applications.</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>Client implementations MUST check the provenance of the pubsub notifications before displaying a notification, otherwise malicious entities could send fake outage events.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>The &REGISTRAR; includes the following information in its registries.</p>
<section2 topic='Field Standardization' anchor='registrar-formtype'>
<p>&xep0068; defines a process for standardizing the fields used within Data Forms qualified by a particular namespace, and <cite>XEP-0128</cite> describes how to use field standardization in the context of service discovery. This section registers fields for server information scoped by the "urn:xmpp:tmp:sos" FORM_TYPE.</p>
<code caption='Registry Submission'><![CDATA[
<form_type>
<name>urn:xmpp:tmp:sos</name>
<doc>XEP-XXXXX</doc>
<desc>
Form enabling a the registration of a machine-readable
external file to describe a service status.
</desc>
<field
var='external-status-addresses'
type='list-multi'
label='One or more addresses containing a file with the server status'/>
</form_type>
]]></code>
</section2>
</section1>
<section1 topic='XML Schema' anchor='schema'>
<p>REQUIRED for protocol specifications.</p>
</section1>
</xep>

View File

@ -1,33 +1,34 @@
(function(){
var o=true,r=null,z=false;window.PR_SHOULD_USE_CONTINUATION=o;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var N=navigator&&navigator.userAgent&&/\bMSIE 6\./.test(navigator.userAgent);window._pr_isIE6=function(){return N};return N};
var aa="!",ba="!=",ca="!==",F="#",da="%",ea="%=",G="&",fa="&&",ja="&&=",ka="&=",H="(",la="*",ma="*=",na="+=",oa=",",pa="-=",qa="->",ra="/",sa="/=",ta=":",ua="::",va=";",I="<",wa="<<",xa="<<=",ya="<=",za="=",Aa="==",Ba="===",J=">",Ca=">=",Da=">>",Ea=">>=",Fa=">>>",Ga=">>>=",Ha="?",Ia="@",L="[",M="^",Ta="^=",Ua="^^",Va="^^=",Wa="{",O="|",Xa="|=",Ya="||",Za="||=",$a="~",ab="break",bb="case",cb="continue",db="delete",eb="do",fb="else",gb="finally",hb="instanceof",ib="return",jb="throw",kb="try",lb="typeof",
mb="(?:^^|[+-]",nb="\\$1",ob=")\\s*",pb="&amp;",qb="&lt;",rb="&gt;",sb="&quot;",tb="&#",ub="x",vb="'",wb='"',xb=" ",yb="XMP",zb="</",Ab='="',P="",Q="\\",Bb="b",Cb="t",Db="n",Eb="v",Fb="f",Gb="r",Hb="u",Ib="0",Jb="1",Kb="2",Lb="3",Mb="4",Nb="5",Ob="6",Pb="7",Qb="\\x0",Rb="\\x",Sb="-",Tb="]",Ub="\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]",R="g",Vb="\\B",Wb="\\b",Xb="\\D",Yb="\\d",Zb="\\S",$b="\\s",ac="\\W",bc="\\w",cc="(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)",
dc="(?:",ec=")",fc="gi",gc="PRE",hc='<!DOCTYPE foo PUBLIC "foo bar">\n<foo />',ic="\t",jc="\n",kc="[^<]+|<!--[\\s\\S]*?--\>|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|</?[a-zA-Z][^>]*>|<",lc="nocode",mc=' $1="$2$3$4"',S="pln",nc="string",T="lang-",oc="src",U="str",pc="'\"",qc="'\"`",rc="\"'",V="com",sc="lang-regex",tc="(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)",uc="kwd",vc="^(?:",wc=")\\b",xc=" \r\n\t\u00a0",yc="lit",zc="typ",Ac="0123456789",Y="pun",Bc="break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try alignof align_union asm axiom bool concept concept_map const_cast constexpr decltype dynamic_cast explicit export friend inline late_check mutable namespace nullptr reinterpret_cast static_assert static_cast template typeid typename typeof using virtual wchar_t where break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient as base by checked decimal delegate descending event fixed foreach from group implicit in interface internal into is lock object out override orderby params partial readonly ref sbyte sealed stackalloc string select uint ulong unchecked unsafe ushort var break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try debugger eval export function get null set undefined var with Infinity NaN caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END break continue do else for if return while case done elif esac eval fi function in local set then until ",
Cc="</span>",Dc='<span class="',Ec='">',Fc="$1&nbsp;",Gc="&nbsp;<br />",Hc="<br />",Ic="console",Jc="cannot override language handler %s",Kc="default-markup",Lc="default-code",Mc="dec",Z="lang-js",$="lang-css",Nc="lang-in.tag",Oc="htm",Pc="html",Qc="mxml",Rc="xhtml",Sc="xml",Tc="xsl",Uc=" \t\r\n",Vc="atv",Wc="tag",Xc="atn",Yc="lang-uq.val",Zc="in.tag",$c="uq.val",ad="break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try alignof align_union asm axiom bool concept concept_map const_cast constexpr decltype dynamic_cast explicit export friend inline late_check mutable namespace nullptr reinterpret_cast static_assert static_cast template typeid typename typeof using virtual wchar_t where ",
bd="c",cd="cc",dd="cpp",ed="cxx",fd="cyc",gd="m",hd="null true false",id="json",jd="break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient as base by checked decimal delegate descending event fixed foreach from group implicit in interface internal into is lock object out override orderby params partial readonly ref sbyte sealed stackalloc string select uint ulong unchecked unsafe ushort var ",
kd="cs",ld="break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient ",md="java",nd="break continue do else for if return while case done elif esac eval fi function in local set then until ",
od="bsh",pd="csh",qd="sh",rd="break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None ",sd="cv",td="py",ud="caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END ",vd="perl",wd="pl",xd="pm",yd="break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END ",
zd="rb",Ad="break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try debugger eval export function get null set undefined var with Infinity NaN ",Bd="js",Cd="regex",Dd="pre",Ed="code",Fd="xmp",Gd="prettyprint",Hd="class",Id="br",Jd="\r";
(function(){var N=function(){for(var a=[aa,ba,ca,F,da,ea,G,fa,ja,ka,H,la,ma,na,oa,pa,qa,ra,sa,ta,ua,va,I,wa,xa,ya,za,Aa,Ba,J,Ca,Da,Ea,Fa,Ga,Ha,Ia,L,M,Ta,Ua,Va,Wa,O,Xa,Ya,Za,$a,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb],b=mb,c=0;c<a.length;++c)b+=O+a[c].replace(/([^=<>:&a-z])/g,nb);b+=ob;return b}(),Ja=/&/g,Ka=/</g,La=/>/g,Kd=/\"/g;function Ld(a){return a.replace(Ja,pb).replace(Ka,qb).replace(La,rb).replace(Kd,sb)}function ga(a){return a.replace(Ja,pb).replace(Ka,qb).replace(La,rb)}var Md=/&lt;/g,Nd=/&gt;/g,
Od=/&apos;/g,Pd=/&quot;/g,Qd=/&amp;/g,Rd=/&nbsp;/g;function Sd(a){var b=a.indexOf(G);if(b<0)return a;for(--b;(b=a.indexOf(tb,b+1))>=0;){var c=a.indexOf(va,b);if(c>=0){var d=a.substring(b+3,c),g=10;if(d&&d.charAt(0)===ub){d=d.substring(1);g=16}var i=parseInt(d,g);isNaN(i)||(a=a.substring(0,b)+String.fromCharCode(i)+a.substring(c+1))}}return a.replace(Md,I).replace(Nd,J).replace(Od,vb).replace(Pd,wb).replace(Qd,G).replace(Rd,xb)}function Ma(a){return yb===a.tagName}function W(a,b){switch(a.nodeType){case 1:var c=
a.tagName.toLowerCase();b.push(I,c);for(var d=0;d<a.attributes.length;++d){var g=a.attributes[d];if(g.specified){b.push(xb);W(g,b)}}b.push(J);for(var i=a.firstChild;i;i=i.nextSibling)W(i,b);if(a.firstChild||!/^(?:br|link|img)$/.test(c))b.push(zb,c,J);break;case 2:b.push(a.name.toLowerCase(),Ab,Ld(a.value),wb);break;case 3:case 4:b.push(ga(a.nodeValue));break}}function Na(a){for(var b=0,c=z,d=z,g=0,i=a.length;g<i;++g){var m=a[g];if(m.ignoreCase)d=o;else if(/[a-z]/i.test(m.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,
P))){c=o;d=z;break}}function l(j){if(j.charAt(0)!==Q)return j.charCodeAt(0);switch(j.charAt(1)){case Bb:return 8;case Cb:return 9;case Db:return 10;case Eb:return 11;case Fb:return 12;case Gb:return 13;case Hb:case ub:return parseInt(j.substring(2),16)||j.charCodeAt(1);case Ib:case Jb:case Kb:case Lb:case Mb:case Nb:case Ob:case Pb:return parseInt(j.substring(1),8);default:return j.charCodeAt(1)}}function n(j){if(j<32)return(j<16?Qb:Rb)+j.toString(16);var f=String.fromCharCode(j);if(f===Q||f===Sb||
f===L||f===Tb)f=Q+f;return f}function q(j){for(var f=j.substring(1,j.length-1).match(new RegExp(Ub,R)),s=[],k=[],h=f[0]===M,e=h?1:0,p=f.length;e<p;++e){var t=f[e];switch(t){case Vb:case Wb:case Xb:case Yb:case Zb:case $b:case ac:case bc:s.push(t);continue}var u=l(t),x;if(e+2<p&&Sb===f[e+1]){x=l(f[e+2]);e+=2}else x=u;k.push([u,x]);if(!(x<65||u>122)){x<65||u>90||k.push([Math.max(65,u)|32,Math.min(x,90)|32]);x<97||u>122||k.push([Math.max(97,u)&-33,Math.min(x,122)&-33])}}k.sort(function(Oa,Pa){return Oa[0]-
Pa[0]||Pa[1]-Oa[1]});var B=[],E=[NaN,NaN];for(e=0;e<k.length;++e){var A=k[e];if(A[0]<=E[1]+1)E[1]=Math.max(E[1],A[1]);else B.push(E=A)}var D=[L];h&&D.push(M);D.push.apply(D,s);for(e=0;e<B.length;++e){A=B[e];D.push(n(A[0]));if(A[1]>A[0]){A[1]+1>A[0]&&D.push(Sb);D.push(n(A[1]))}}D.push(Tb);return D.join(P)}function v(j){var f=j.source.match(new RegExp(cc,R)),s=f.length,k=[],h,e=0;for(h=0;e<s;++e){var p=f[e];if(p===H)++h;else if(Q===p.charAt(0)){var t=+p.substring(1);if(t&&t<=h)k[t]=-1}}for(e=1;e<k.length;++e)if(-1===
k[e])k[e]=++b;for(h=e=0;e<s;++e){p=f[e];if(p===H){++h;if(k[h]===undefined)f[e]=dc}else if(Q===p.charAt(0))if((t=+p.substring(1))&&t<=h)f[e]=Q+k[h]}for(h=e=0;e<s;++e)if(M===f[e]&&M!==f[e+1])f[e]=P;if(j.ignoreCase&&c)for(e=0;e<s;++e){p=f[e];var u=p.charAt(0);if(p.length>=2&&u===L)f[e]=q(p);else if(u!==Q)f[e]=p.replace(/[a-zA-Z]/g,function(x){var B=x.charCodeAt(0);return L+String.fromCharCode(B&-33,B|32)+Tb})}return f.join(P)}var w=[];g=0;for(i=a.length;g<i;++g){m=a[g];if(m.global||m.multiline)throw new Error(P+
m);w.push(dc+v(m)+ec)}return new RegExp(w.join(O),d?fc:R)}var ha=r;function Td(a){if(r===ha){var b=document.createElement(gc);b.appendChild(document.createTextNode(hc));ha=!/</.test(b.innerHTML)}if(ha){var c=a.innerHTML;if(Ma(a))c=ga(c);return c}for(var d=[],g=a.firstChild;g;g=g.nextSibling)W(g,d);return d.join(P)}function Ud(a){var b=0;return function(c){for(var d=r,g=0,i=0,m=c.length;i<m;++i){var l=c.charAt(i);switch(l){case ic:d||(d=[]);d.push(c.substring(g,i));var n=a-b%a;for(b+=n;n>=0;n-=" ".length)d.push(" ".substring(0,
n));g=i+1;break;case jc:b=0;break;default:++b}}if(!d)return c;d.push(c.substring(g));return d.join(P)}}var Vd=new RegExp(kc,R),Wd=/^<\!--/,Xd=/^<\[CDATA\[/,Yd=/^<br\b/i,Qa=/^<(\/?)([a-zA-Z]+)/;function Zd(a){var b=a.match(Vd),c=[],d=0,g=[];if(b)for(var i=0,m=b.length;i<m;++i){var l=b[i];if(l.length>1&&l.charAt(0)===I){if(!Wd.test(l))if(Xd.test(l)){c.push(l.substring(9,l.length-3));d+=l.length-12}else if(Yd.test(l)){c.push(jc);++d}else if(l.indexOf(lc)>=0&&$d(l)){var n=l.match(Qa)[2],q=1,v;v=i+1;a:for(;v<
m;++v){var w=b[v].match(Qa);if(w&&w[2]===n)if(w[1]===ra){if(--q===0)break a}else++q}if(v<m){g.push(d,b.slice(i,v+1).join(P));i=v}else g.push(d,l)}else g.push(d,l)}else{var j=Sd(l);c.push(j);d+=j.length}}return{source:c.join(P),tags:g}}function $d(a){return!!a.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,mc).match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)}function ia(a,b,c,d){if(b){var g={source:b,b:a};c(g);d.push.apply(d,g.c)}}function K(a,b){var c={},d;(function(){for(var m=a.concat(b),
l=[],n={},q=0,v=m.length;q<v;++q){var w=m[q],j=w[3];if(j)for(var f=j.length;--f>=0;)c[j.charAt(f)]=w;var s=w[1],k=P+s;if(!n.hasOwnProperty(k)){l.push(s);n[k]=r}}l.push(/[\0-\uffff]/);d=Na(l)})();var g=b.length,i=function(m){for(var l=m.source,n=m.b,q=[n,S],v=0,w=l.match(d)||[],j={},f=0,s=w.length;f<s;++f){var k=w[f],h=j[k],e,p;if(typeof h===nc)p=z;else{var t=c[k.charAt(0)];if(t){e=k.match(t[1]);h=t[0]}else{for(var u=0;u<g;++u){t=b[u];if(e=k.match(t[1])){h=t[0];break}}e||(h=S)}if((p=h.length>=5&&T===
h.substring(0,5))&&!(e&&e[1])){p=z;h=oc}p||(j[k]=h)}var x=v;v+=k.length;if(p){var B=e[1],E=k.indexOf(B),A=E+B.length,D=h.substring(5);ia(n+x,k.substring(0,E),i,q);ia(n+x+E,B,Ra(D,B),q);ia(n+x+A,k.substring(A),i,q)}else q.push(n+x,h)}m.c=q};return i}function C(a){var b=[],c=[];if(a.tripleQuotedStrings)b.push([U,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,r,pc]);
else a.multiLineStrings?b.push([U,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,r,qc]):b.push([U,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,r,rc]);if(a.hashComments)a.cStyleComments?b.push([V,/^#(?:[^\r\n\/]|\/(?!\*)|\/\*[^\r\n]*?\*\/)*/,r,F]):b.push([V,/^#[^\r\n]*/,r,F]);if(a.cStyleComments){c.push([V,/^\/\/[^\r\n]*/,r]);c.push([V,/^\/\*[\s\S]*?(?:\*\/|$)/,r])}a.regexLiterals&&c.push([sc,new RegExp(M+N+tc)]);var d=
a.keywords.replace(/^\s+|\s+$/g,P);d.length&&c.push([uc,new RegExp(vc+d.replace(/\s+/g,O)+wc),r]);b.push([S,/^\s+/,r,xc]);c.push([yc,/^@[a-z_$][a-z_$@0-9]*/i,r,Ia],[zc,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/,r],[S,/^[a-z_$][a-z_$@0-9]*/i,r],[yc,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,r,Ac],[Y,/^.[^\s\w\.$@\'\"\`\/\#]*/,r]);return K(b,c)}var ae=C({keywords:Bc,hashComments:o,cStyleComments:o,multiLineStrings:o,regexLiterals:o});function be(a){var b=a.source,c=a.f,d=a.c,
g=[],i=0,m=r,l=r,n=0,q=0,v=Ud(window.PR_TAB_WIDTH),w=/([\r\n ]) /g,j=/(^| ) /gm,f=/\r\n?|\n/g,s=/[ \r\n]$/,k=o;function h(p){if(p>i){if(m&&m!==l){g.push(Cc);m=r}if(!m&&l){m=l;g.push(Dc,m,Ec)}var t=ga(v(b.substring(i,p))).replace(k?j:w,Fc);k=s.test(t);var u=window._pr_isIE6()?Gc:Hc;g.push(t.replace(f,u));i=p}}for(;1;){var e;if(e=n<c.length?q<d.length?c[n]<=d[q]:o:z){h(c[n]);if(m){g.push(Cc);m=r}g.push(c[n+1]);n+=2}else if(q<d.length){h(d[q]);l=d[q+1];q+=2}else break}h(b.length);m&&g.push(Cc);a.a=g.join(P)}
var X={};function y(a,b){for(var c=b.length;--c>=0;){var d=b[c];if(X.hasOwnProperty(d))Ic in window&&console.i(Jc,d);else X[d]=a}}function Ra(a,b){a&&X.hasOwnProperty(a)||(a=/^\s*</.test(b)?Kc:Lc);return X[a]}y(ae,[Lc]);y(K([],[[S,/^[^<?]+/],[Mc,/^<!\w[^>]*(?:>|$)/],[V,/^<\!--[\s\S]*?(?:-\->|$)/],[T,/^<\?([\s\S]+?)(?:\?>|$)/],[T,/^<%([\s\S]+?)(?:%>|$)/],[Y,/^(?:<[%?]|[%?]>)/],[T,/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],[Z,/^<script\b[^>]*>([\s\S]+?)<\/script\b[^>]*>/i],[$,/^<style\b[^>]*>([\s\S]+?)<\/style\b[^>]*>/i],
[Nc,/^(<\/?[a-z][^<>]*>)/i]]),[Kc,Oc,Pc,Qc,Rc,Sc,Tc]);y(K([[S,/^[\s]+/,r,Uc],[Vc,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,r,rc]],[[Wc,/^^<\/?[a-z](?:[\w:-]*\w)?|\/?>$/],[Xc,/^(?!style\b|on)[a-z](?:[\w:-]*\w)?/],[Yc,/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[Y,/^[=<>\/]+/],[Z,/^on\w+\s*=\s*\"([^\"]+)\"/i],[Z,/^on\w+\s*=\s*\'([^\']+)\'/i],[Z,/^on\w+\s*=\s*([^\"\'>\s]+)/i],[$,/^sty\w+\s*=\s*\"([^\"]+)\"/i],[$,/^sty\w+\s*=\s*\'([^\']+)\'/i],[$,/^sty\w+\s*=\s*([^\"\'>\s]+)/i]]),[Zc]);y(K([],[[Vc,/^[\s\S]+/]]),
[$c]);y(C({keywords:ad,hashComments:o,cStyleComments:o}),[bd,cd,dd,ed,fd,gd]);y(C({keywords:hd}),[id]);y(C({keywords:jd,hashComments:o,cStyleComments:o}),[kd]);y(C({keywords:ld,cStyleComments:o}),[md]);y(C({keywords:nd,hashComments:o,multiLineStrings:o}),[od,pd,qd]);y(C({keywords:rd,hashComments:o,multiLineStrings:o,tripleQuotedStrings:o}),[sd,td]);y(C({keywords:ud,hashComments:o,multiLineStrings:o,regexLiterals:o}),[vd,wd,xd]);y(C({keywords:yd,hashComments:o,multiLineStrings:o,regexLiterals:o}),
[zd]);y(C({keywords:Ad,cStyleComments:o,regexLiterals:o}),[Bd]);y(K([],[[U,/^[\s\S]+/]]),[Cd]);function Sa(a){var b=a.e,c=a.d;a.a=b;try{var d=Zd(b),g=d.source;a.source=g;a.b=0;a.f=d.tags;Ra(c,g)(a);be(a)}catch(i){if(Ic in window){console.log(i);console.h()}}}function ce(a,b){var c={e:a,d:b};Sa(c);return c.a}function de(a){for(var b=window._pr_isIE6(),c=[document.getElementsByTagName(Dd),document.getElementsByTagName(Ed),document.getElementsByTagName(Fd)],d=[],g=0;g<c.length;++g)for(var i=0,m=c[g].length;i<
m;++i)d.push(c[g][i]);c=r;var l=Date;l.now||(l={now:function(){return(new Date).getTime()}});var n=0,q;function v(){for(var j=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;n<d.length&&l.now()<j;n++){var f=d[n];if(f.className&&f.className.indexOf(Gd)>=0){var s=f.className.match(/\blang-(\w+)\b/);if(s)s=s[1];for(var k=z,h=f.parentNode;h;h=h.parentNode)if((h.tagName===Dd||h.tagName===Ed||h.tagName===Fd)&&h.className&&h.className.indexOf(Gd)>=0){k=o;break}if(!k){var e=Td(f);e=e.replace(/(?:\r\n?|\n)$/,
P);q={e:e,d:s,g:f};Sa(q);w()}}}if(n<d.length)setTimeout(v,250);else a&&a()}function w(){var j=q.a;if(j){var f=q.g;if(Ma(f)){for(var s=document.createElement(gc),k=0;k<f.attributes.length;++k){var h=f.attributes[k];if(h.specified){var e=h.name.toLowerCase();if(e===Hd)s.className=h.value;else s.setAttribute(h.name,h.value)}}s.innerHTML=j;f.parentNode.replaceChild(s,f);f=s}else f.innerHTML=j;if(b&&f.tagName===gc)for(var p=f.getElementsByTagName(Id),t=p.length;--t>=0;){var u=p[t];u.parentNode.replaceChild(document.createTextNode(Jd),
u)}}}v()}window.PR_normalizedHtml=W;window.prettyPrintOne=ce;window.prettyPrint=de;window.PR={combinePrefixPatterns:Na,createSimpleLexer:K,registerLangHandler:y,sourceDecorator:C,PR_ATTRIB_NAME:Xc,PR_ATTRIB_VALUE:Vc,PR_COMMENT:V,PR_DECLARATION:Mc,PR_KEYWORD:uc,PR_LITERAL:yc,PR_NOCODE:lc,PR_PLAIN:S,PR_PUNCTUATION:Y,PR_SOURCE:oc,PR_STRING:U,PR_TAG:Wc,PR_TYPE:zc}})();
})()
/*
* Build of https://github.com/googlearchive/code-prettify
* Under the Apache 2 License
*/
!function(a,b){"undefined"!=typeof window&&(window.PR_SHOULD_USE_CONTINUATION=!0);!function(){function a(a){function b(a){var b=a.charCodeAt(0);if(92!==b)return b;var c=a.charAt(1);return(b=k[c])||("0"<=c&&c<="7"?parseInt(a.substring(1),8):"u"===c||"x"===c?parseInt(a.substring(2),16):a.charCodeAt(1))}function c(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);var b=String.fromCharCode(a);return"\\"===b||"-"===b||"]"===b||"^"===b?"\\"+b:b}function d(a){
var d=a.substring(1,a.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g")),e=[],f="^"===d[0],g=["["];f&&g.push("^");for(var h=f?1:0,i=d.length;h<i;++h){var j=d[h];if(/\\[bdsw]/i.test(j))g.push(j);else{var k,l=b(j);h+2<i&&"-"===d[h+1]?(k=b(d[h+2]),h+=2):k=l,e.push([l,k]),k<65||l>122||(k<65||l>90||e.push([32|Math.max(65,l),32|Math.min(k,90)]),k<97||l>122||e.push([-33&Math.max(97,l),-33&Math.min(k,122)]))}}
e.sort(function(a,b){return a[0]-b[0]||b[1]-a[1]});for(var m=[],n=[],h=0;h<e.length;++h){var o=e[h];o[0]<=n[1]+1?n[1]=Math.max(n[1],o[1]):m.push(n=o)}for(var h=0;h<m.length;++h){var o=m[h];g.push(c(o[0])),o[1]>o[0]&&(o[1]+1>o[0]&&g.push("-"),g.push(c(o[1])))}return g.push("]"),g.join("")}for(var e=0,f=!1,g=!1,h=0,i=a.length;h<i;++h){var j=a[h];if(j.ignoreCase)g=!0;else if(/[a-z]/i.test(j.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){f=!0,g=!1;break}}for(var k={b:8,t:9,n:10,v:11,
f:12,r:13},l=[],h=0,i=a.length;h<i;++h){var j=a[h];if(j.global||j.multiline)throw new Error(""+j);l.push("(?:"+function(a){for(var b=a.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),g=b.length,h=[],i=0,j=0;i<g;++i){var k=b[i];if("("===k)++j;else if("\\"===k.charAt(0)){var l=+k.substring(1);l&&(l<=j?h[l]=-1:b[i]=c(l))}}
for(var i=1;i<h.length;++i)-1===h[i]&&(h[i]=++e);for(var i=0,j=0;i<g;++i){var k=b[i];if("("===k)++j,h[j]||(b[i]="(?:");else if("\\"===k.charAt(0)){var l=+k.substring(1);l&&l<=j&&(b[i]="\\"+h[l])}}for(var i=0;i<g;++i)"^"===b[i]&&"^"!==b[i+1]&&(b[i]="");if(a.ignoreCase&&f)for(var i=0;i<g;++i){var k=b[i],m=k.charAt(0);k.length>=2&&"["===m?b[i]=d(k):"\\"!==m&&(b[i]=k.replace(/[a-zA-Z]/g,function(a){var b=a.charCodeAt(0);return"["+String.fromCharCode(-33&b,32|b)+"]"}))}return b.join("")}(j)+")")}
return new RegExp(l.join("|"),g?"gi":"g")}function b(a,b){function c(a){var i=a.nodeType;if(1==i){if(d.test(a.className))return;for(var j=a.firstChild;j;j=j.nextSibling)c(j);var k=a.nodeName.toLowerCase();"br"!==k&&"li"!==k||(e[h]="\n",g[h<<1]=f++,g[h++<<1|1]=a)}else if(3==i||4==i){var l=a.nodeValue;l.length&&(l=b?l.replace(/\r\n?/g,"\n"):l.replace(/[ \t\r\n]+/g," "),e[h]=l,g[h<<1]=f,f+=l.length,g[h++<<1|1]=a)}}var d=/(?:^|\s)nocode(?:\s|$)/,e=[],f=0,g=[],h=0;return c(a),{
sourceCode:e.join("").replace(/\n$/,""),spans:g}}function c(a,b,c,d,e){if(c){var f={sourceNode:a,pre:1,langExtension:null,numberLines:null,sourceCode:c,spans:null,basePos:b,decorations:null};d(f),e.push.apply(e,f.decorations)}}function d(a){for(var b=undefined,c=a.firstChild;c;c=c.nextSibling){var d=c.nodeType;b=1===d?b?a:c:3===d&&K.test(c.nodeValue)?a:b}return b===a?undefined:b}function e(b,d){var e,f={};!function(){for(var c=b.concat(d),g=[],h={},i=0,j=c.length;i<j;++i){var k=c[i],l=k[3]
;if(l)for(var m=l.length;--m>=0;)f[l.charAt(m)]=k;var n=k[1],o=""+n;h.hasOwnProperty(o)||(g.push(n),h[o]=null)}g.push(/[\0-\uffff]/),e=a(g)}();var g=d.length,h=function(a){for(var b=a.sourceCode,i=a.basePos,k=a.sourceNode,l=[i,H],m=0,n=b.match(e)||[],o={},p=0,q=n.length;p<q;++p){var r,s=n[p],t=o[s],u=void 0;if("string"==typeof t)r=!1;else{var v=f[s.charAt(0)];if(v)u=s.match(v[1]),t=v[0];else{for(var w=0;w<g;++w)if(v=d[w],u=s.match(v[1])){t=v[0];break}u||(t=H)}
r=t.length>=5&&"lang-"===t.substring(0,5),!r||u&&"string"==typeof u[1]||(r=!1,t=I),r||(o[s]=t)}var x=m;if(m+=s.length,r){var y=u[1],z=s.indexOf(y),A=z+y.length;u[2]&&(A=s.length-u[2].length,z=A-y.length);var B=t.substring(5);c(k,i+x,s.substring(0,z),h,l),c(k,i+x+z,y,j(B,y),l),c(k,i+x+A,s.substring(A),h,l)}else l.push(i+x,t)}a.decorations=l};return h}function f(a){var b=[],c=[]
;a.tripleQuotedStrings?b.push([B,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""]):a.multiLineStrings?b.push([B,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):b.push([B,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]),
a.verbatimStrings&&c.push([B,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var d=a.hashComments;d&&(a.cStyleComments?(d>1?b.push([D,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):b.push([D,/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]),c.push([B,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):b.push([D,/^#[^\r\n]*/,null,"#"])),a.cStyleComments&&(c.push([D,/^\/\/[^\r\n]*/,null]),
c.push([D,/^\/\*[\s\S]*?(?:\*\/|$)/,null]));var f=a.regexLiterals;if(f){var g=f>1?"":"\n\r",h=g?".":"[\\S\\s]",i="/(?=[^/*"+g+"])(?:[^/\\x5B\\x5C"+g+"]|\\x5C"+h+"|\\x5B(?:[^\\x5C\\x5D"+g+"]|\\x5C"+h+")*(?:\\x5D|$))+/";c.push(["lang-regex",RegExp("^"+J+"("+i+")")])}var j=a.types;j&&c.push([E,j]);var k=(""+a.keywords).replace(/^ | $/g,"");k.length&&c.push([C,new RegExp("^(?:"+k.replace(/[\s,]+/g,"|")+")\\b"),null]),b.push([H,/^\s+/,null," \r\n\t\xa0"]);var l="^.[^\\s\\w.$@'\"`/\\\\]*"
;return a.regexLiterals&&(l+="(?!s*/)"),c.push([F,/^@[a-z_$][a-z_$@0-9]*/i,null],[E,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[H,/^[a-z_$][a-z_$@0-9]*/i,null],[F,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[H,/^\\[\s\S]?/,null],[G,new RegExp(l),null]),e(b,c)}function g(a,b,c){function d(a){var b=a.nodeType;if(1!=b||f.test(a.className)){if((3==b||4==b)&&c){var i=a.nodeValue,j=i.match(g);if(j){
var k=i.substring(0,j.index);a.nodeValue=k;var l=i.substring(j.index+j[0].length);if(l){var m=a.parentNode;m.insertBefore(h.createTextNode(l),a.nextSibling)}e(a),k||a.parentNode.removeChild(a)}}}else if("br"===a.nodeName.toLowerCase())e(a),a.parentNode&&a.parentNode.removeChild(a);else for(var n=a.firstChild;n;n=n.nextSibling)d(n)}function e(a){function b(a,c){var d=c?a.cloneNode(!1):a,e=a.parentNode;if(e){var f=b(e,1),g=a.nextSibling;f.appendChild(d);for(var h=g;h;h=g)g=h.nextSibling,
f.appendChild(h)}return d}for(;!a.nextSibling;)if(!(a=a.parentNode))return;for(var c,d=b(a.nextSibling,0);(c=d.parentNode)&&1===c.nodeType;)d=c;j.push(d)}for(var f=/(?:^|\s)nocode(?:\s|$)/,g=/\r\n?|\n/,h=a.ownerDocument,i=h.createElement("li");a.firstChild;)i.appendChild(a.firstChild);for(var j=[i],k=0;k<j.length;++k)d(j[k]);b===(0|b)&&j[0].setAttribute("value",b);var l=h.createElement("ol");l.className="linenums";for(var m=Math.max(0,b-1|0)||0,k=0,n=j.length;k<n;++k)i=j[k],
i.className="L"+(k+m)%10,i.firstChild||i.appendChild(h.createTextNode("\xa0")),l.appendChild(i);a.appendChild(l)}function h(a){var b=/\bMSIE\s(\d+)/.exec(navigator.userAgent);b=b&&+b[1]<=8;var c=/\n/g,d=a.sourceCode,e=d.length,f=0,g=a.spans,h=g.length,i=0,j=a.decorations,k=j.length,l=0;j[k]=e;var m,n;for(n=m=0;n<k;)j[n]!==j[n+2]?(j[m++]=j[n++],j[m++]=j[n++]):n+=2;for(k=m,n=m=0;n<k;){for(var o=j[n],p=j[n+1],q=n+2;q+2<=k&&j[q+1]===p;)q+=2;j[m++]=o,j[m++]=p,n=q}k=j.length=m;var r=a.sourceNode,s=""
;r&&(s=r.style.display,r.style.display="none");try{for(;i<h;){var t,u=(g[i],g[i+2]||e),v=j[l+2]||e,q=Math.min(u,v),w=g[i+1];if(1!==w.nodeType&&(t=d.substring(f,q))){b&&(t=t.replace(c,"\r")),w.nodeValue=t;var x=w.ownerDocument,y=x.createElement("span");y.className=j[l+1];var z=w.parentNode;z.replaceChild(y,w),y.appendChild(w),f<u&&(g[i+1]=w=x.createTextNode(d.substring(q,u)),z.insertBefore(w,y.nextSibling))}f=q,f>=u&&(i+=2),f>=v&&(l+=2)}}finally{r&&(r.style.display=s)}}function i(a,b){
for(var c=b.length;--c>=0;){var d=b[c];M.hasOwnProperty(d)?n.console&&console.warn("cannot override language handler %s",d):M[d]=a}}function j(a,b){return a&&M.hasOwnProperty(a)||(a=/^\s*</.test(b)?"default-markup":"default-code"),M[a]}function k(a){var c=a.langExtension;try{var d=b(a.sourceNode,a.pre),e=d.sourceCode;a.sourceCode=e,a.spans=d.spans,a.basePos=0,j(c,e)(a),h(a)}catch(f){n.console&&console.log(f&&f.stack||f)}}function l(a,b,c){var d=c||!1,e=b||null,f=document.createElement("div")
;return f.innerHTML="<pre>"+a+"</pre>",f=f.firstChild,d&&g(f,d,!0),k({langExtension:e,numberLines:d,sourceNode:f,pre:1,sourceCode:null,basePos:null,spans:null,decorations:null}),f.innerHTML}function m(a,b){function c(a){return f.getElementsByTagName(a)}function e(){for(var b=n.PR_SHOULD_USE_CONTINUATION?p.now()+250:Infinity;q<j.length&&p.now()<b;q++){for(var c=j[q],f=x,i=c;i=i.previousSibling;){var l=i.nodeType,m=(7===l||8===l)&&i.nodeValue
;if(m?!/^\??prettify\b/.test(m):3!==l||/\S/.test(i.nodeValue))break;if(m){f={},m.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){f[b]=c});break}}var o=c.className;if((f!==x||s.test(o))&&!t.test(o)){for(var y=!1,z=c.parentNode;z;z=z.parentNode){var A=z.tagName;if(w.test(A)&&z.className&&s.test(z.className)){y=!0;break}}if(!y){c.className+=" prettyprinted";var B=f.lang;if(!B){B=o.match(r);var C;!B&&(C=d(c))&&v.test(C.tagName)&&(B=C.className.match(r)),B&&(B=B[1])}var D
;if(u.test(c.tagName))D=1;else{var E=c.currentStyle,F=h.defaultView,G=E?E.whiteSpace:F&&F.getComputedStyle?F.getComputedStyle(c,null).getPropertyValue("white-space"):0;D=G&&"pre"===G.substring(0,3)}var H=f.linenums;(H="true"===H||+H)||(H=o.match(/\blinenums\b(?::(\d+))?/),H=!!H&&(!H[1]||!H[1].length||+H[1])),H&&g(c,H,D);k({langExtension:B,sourceNode:c,numberLines:H,pre:D,sourceCode:null,basePos:null,spans:null,decorations:null})}}}q<j.length?n.setTimeout(e,250):"function"==typeof a&&a()}
for(var f=b||document.body,h=f.ownerDocument||document,i=[c("pre"),c("code"),c("xmp")],j=[],l=0;l<i.length;++l)for(var m=0,o=i[l].length;m<o;++m)j.push(i[l][m]);i=null;var p=Date;p.now||(p={now:function(){return+new Date}});var q=0,r=/\blang(?:uage)?-([\w.]+)(?!\S)/,s=/\bprettyprint\b/,t=/\bprettyprinted\b/,u=/pre|xmp/i,v=/^code$/i,w=/^(?:pre|code|xmp)$/i,x={};e()}
var n="undefined"!=typeof window?window:{},o=["break,continue,do,else,for,if,return,while"],p=[o,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],q=[p,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],r=[q,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],s=[q,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],t=[q,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],u=[q,"abstract,async,await,constructor,debugger,enum,eval,export,from,function,get,import,implements,instanceof,interface,let,null,of,set,undefined,var,with,yield,Infinity,NaN"],v="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",w=[o,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],x=[o,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],y=[o,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],z=[r,t,s,u,v,w,x,y],A=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,B="str",C="kwd",D="com",E="typ",F="lit",G="pun",H="pln",I="src",J="(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*",K=/\S/,L=f({
keywords:z,hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),M={};i(L,["default-code"]),
i(e([],[[H,/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],[D,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[G,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]),
i(e([[H,/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[G,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]),
i(e([],[["atv",/^[\s\S]+/]]),["uq.val"]),i(f({keywords:r,hashComments:!0,cStyleComments:!0,types:A}),["c","cc","cpp","cxx","cyc","m"]),i(f({keywords:"null,true,false"}),["json"]),i(f({keywords:t,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:A}),["cs"]),i(f({keywords:s,cStyleComments:!0}),["java"]),i(f({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]),i(f({keywords:w,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]),i(f({
keywords:v,hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]),i(f({keywords:x,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]),i(f({keywords:u,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]),i(f({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,
tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]),i(e([],[[B,/^[\s\S]+/]]),["regex"]);var N=n.PR={createSimpleLexer:e,registerLangHandler:i,sourceDecorator:f,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:D,PR_DECLARATION:"dec",PR_KEYWORD:C,PR_LITERAL:F,PR_NOCODE:"nocode",PR_PLAIN:H,PR_PUNCTUATION:G,PR_SOURCE:I,PR_STRING:B,PR_TAG:"tag",PR_TYPE:E,prettyPrintOne:n.prettyPrintOne=l,prettyPrint:n.prettyPrint=m},O=n.define
;"function"==typeof O&&O.amd&&O("google-code-prettify",[],function(){return N})}(),b["true"]=a}({},function(){return this}());

View File

@ -2,7 +2,7 @@
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY ns "urn:xmpp:trust-messages:0">
<!ENTITY ns-example-usage "urn:xmpp:example-usage:0">
<!ENTITY ns-atm "urn:xmpp:atm:0">
<!ENTITY ns-omemo "urn:xmpp:omemo:1">
<!ENTITY ns-sce "urn:xmpp:sce:0">
%ents;
@ -36,6 +36,19 @@
<email>melvo@olomono.de</email>
<jid>melvo@olomono.de</jid>
</author>
<revision>
<version>0.3.0</version>
<date>2020-12-19</date>
<initials>melvo</initials>
<remark>
<p>Clarify usage, use real namespace for examples and add missing section:</p>
<ul>
<li>Clarify usage of trust messages by protocols such as &xep0450;</li>
<li>Use namespace 'urn:xmpp:atm:0' of &xep0450; as example for 'usage' attribute.</li>
<li>Add section 'Security Considerations'</li>
</ul>
</remark>
</revision>
<revision>
<version>0.2.0</version>
<date>2020-11-05</date>
@ -124,6 +137,7 @@
<section1 topic='Why Trust Messages?' anchor='why-trust-messages'>
<p>
Trust messages can be used in conjunction with an end-to-end encryption protocol such as &xep0373; or &xep0384; to automatically or semi-automatically establish secure channels protected against active attacks.
This protocol specifies how trust messages are transmitted and protocols such as &xep0450; specify how and for which purpose they are processed.
</p>
<section2 topic='General Advantages' anchor='why-trust-messages-general-advantages'>
<p>
@ -244,8 +258,8 @@
<p>
In the following example, two &xep0384; keys of Alice are indicated as trusted, one key of Bob is indicated as trusted and two other ones of Bob are indicated as untrusted.
</p>
<example caption='Trust Message Element for Alice&apos;s and Bob&apos;s OMEMO Keys'><![CDATA[
<trust-message xmlns=']]>&ns;<![CDATA[' usage=']]>&ns-example-usage;<![CDATA[' encryption=']]>&ns-omemo;<![CDATA['>
<example caption='Trust Message Element for Alice&apos;s and Bob&apos;s OMEMO Keys used by ATM'><![CDATA[
<trust-message xmlns=']]>&ns;<![CDATA[' usage=']]>&ns-atm;<![CDATA[' encryption=']]>&ns-omemo;<![CDATA['>
<key-owner jid='alice@example.org'>
<trust>6850019d7ed0feb6d3823072498ceb4f616c6025586f8f666dc6b9c81ef7e0a4</trust>
<trust>221a4f8e228b72182b006e5ca527d3bddccf8d9e6feaf4ce96e1c451e8648020</trust>
@ -310,7 +324,7 @@
<from jid='alice@example.org/notebook'/>
<to jid='carol@example.com'/>
<payload>
<trust-message xmlns=']]>&ns;<![CDATA[' usage=']]>&ns-example-usage;<![CDATA[' encryption=']]>&ns-omemo;<![CDATA['>
<trust-message xmlns=']]>&ns;<![CDATA[' usage=']]>&ns-atm;<![CDATA[' encryption=']]>&ns-omemo;<![CDATA['>
<key-owner jid='alice@example.org'>
<trust>6850019d7ed0feb6d3823072498ceb4f616c6025586f8f666dc6b9c81ef7e0a4</trust>
<trust>221a4f8e228b72182b006e5ca527d3bddccf8d9e6feaf4ce96e1c451e8648020</trust>
@ -353,6 +367,12 @@
Keep in mind that a trust message SHOULD only be encrypted for endpoints with authenticated keys.
</p>
</section1>
<section1 topic='Security Considerations' anchor='security-considerations'>
<p>
Protocols using trust messages SHOULD specify rules for processing them in order to create or sustain a secure communication.
Therefore, those protocols SHOULD state in which cases from which senders trust messages are used for making trust decisions and for which keys they are sent to whom.
</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana-considerations'>
<p>This document requires no interaction with the Internet Assigned Numbers Authority (IANA).</p>
</section1>