diff options
Diffstat (limited to 'secret-service')
-rw-r--r-- | secret-service/.gitignore | 3 | ||||
-rw-r--r-- | secret-service/Makefile | 10 | ||||
-rw-r--r-- | secret-service/README | 20 | ||||
-rw-r--r-- | secret-service/docbook-params.xsl | 39 | ||||
-rw-r--r-- | secret-service/html/style.css | 127 | ||||
-rw-r--r-- | secret-service/org.freedesktop.Secrets.xml | 427 | ||||
-rw-r--r-- | secret-service/specification.xml | 505 | ||||
-rw-r--r-- | secret-service/tools/resolve-type.xsl | 122 | ||||
-rw-r--r-- | secret-service/tools/spec-to-docbook.xsl | 1239 | ||||
-rw-r--r-- | secret-service/tools/spec-to-introspect.xsl | 147 |
10 files changed, 2639 insertions, 0 deletions
diff --git a/secret-service/.gitignore b/secret-service/.gitignore new file mode 100644 index 0000000..551e415 --- /dev/null +++ b/secret-service/.gitignore @@ -0,0 +1,3 @@ + +/html/*.html +reference.xml diff --git a/secret-service/Makefile b/secret-service/Makefile new file mode 100644 index 0000000..27084aa --- /dev/null +++ b/secret-service/Makefile @@ -0,0 +1,10 @@ + +SPEC = org.freedesktop.Secrets.xml + +all: html/index.html + +html/index.html: reference.xml docbook-params.xsl specification.xml + xmlto --skip-validation -o html/ -x docbook-params.xsl xhtml specification.xml + +reference.xml: tools/spec-to-docbook.xsl $(SPEC) + xsltproc tools/spec-to-docbook.xsl $(SPEC) > $@ diff --git a/secret-service/README b/secret-service/README new file mode 100644 index 0000000..72a9997 --- /dev/null +++ b/secret-service/README @@ -0,0 +1,20 @@ +Generating the specification consists of separate steps: + +1. Use an xslt processor to create a DocBook XML document from the Telepathy + Introspection document using the provided stylesheet: + +$ xsltproc tools/spec-to-docbook.xsl \ + org.freedesktop.Secrets.xml >reference.xml + +2. Convert specification.xml and reference.xml to a suitable output format + (specification.xml includes reference.xml), eg html: + +$ xmlto --skip-validation -o html -p params-html.xsl xhtml specification.xml + +If you choose a different directory for html generation, be sure to copy +html/style.css to that location. + +Then open the resulting html/index.html in your favourite browser. + + +Michael Leupold <lemma@confuego.org> diff --git a/secret-service/docbook-params.xsl b/secret-service/docbook-params.xsl new file mode 100644 index 0000000..5d8591a --- /dev/null +++ b/secret-service/docbook-params.xsl @@ -0,0 +1,39 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<!-- + Parameters for DocBook transformation. + + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +--> + + <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"/> + + <xsl:param name="toc.max.depth">3</xsl:param> + <xsl:param name="generate.section.toc.level">0</xsl:param> + <xsl:param name="generate.toc"> + book toc + part nop + chapter toc + </xsl:param> + <xsl:param name="html.stylesheet">style.css</xsl:param> + <xsl:param name="funcsynopsis.style">ansi</xsl:param> + <xsl:param name="funcsynopsis.decoration">1</xsl:param> + <xsl:param name="refentry.generate.name">0</xsl:param> + <xsl:param name="refentry.generate.title">1</xsl:param> + +</xsl:stylesheet> diff --git a/secret-service/html/style.css b/secret-service/html/style.css new file mode 100644 index 0000000..f8a03b0 --- /dev/null +++ b/secret-service/html/style.css @@ -0,0 +1,127 @@ +/* reference.css, a stylesheet for reference documentation + * generated by the DocBook XSL Stylesheets */ +/* $Id: reference.css 8234 2009-02-09 12:10:48Z xmldoc $ */ + +div.legalnotice { + font-size: 80%; +} + +div.note, div.tip, div.warning { + margin-left: 5%; + margin-right: 10%; + padding: 5px; +} + +div.note, div.tip { + border-left: solid #d5dee3 20px; + border-right: solid #d5dee3 20px; +} + +div.note, div.tip { + border-left: solid palegreen 20px; + border-right: solid palegreen 20px; +} + +div.warning { + border-left: solid yellow 20px; + border-right: solid yellow 20px; +} + +div.note p, div.tip p, div.warning p { + margin-top: 0px; + margin-bottom: 4px; +} + +div.note h3, div.tip h3, div.warning h3 { + margin-top: 0; +} + +div.informalexample { + background-color: #d5dee3; + border-top-width: 2px; + border-top-style: double; + border-top-color: #d3d3d3; + border-bottom-width: 2px; + border-bottom-style: double; + border-bottom-color: #d3d3d3; + padding: 4px; + margin: 0em; + margin-left: 2em; +} + +pre.programlisting, pre.synopsis { + whitespace: pre; + font-family: monospace; + background-color: #d5dee3; + border-top-width: 1px; + border-top-style: single; + border-top-color: #d3d3d3; + border-bottom-width: 1px; + border-bottom-style: single; + border-bottom-color: #d3d3d3; + padding: 4px; + margin: 0em; + margin-top: 6px; + margin-bottom: 6px; +} + +div.informalexample pre { + whitespace: pre; + font-family: monospace; + border-top-width: 0px; + border-bottom-width: 0px; + padding: 0px; +} + +/* Parameter and PI titles */ + div.refnamediv h2 { + font-size: 2em; +} + +div.funcsynopsis, code.fieldsynopsis, +div.refsect2 div.refsynopsisdiv { + padding: 0.5em; + background-color: #F4F4F4; + border: 1px solid gray; + display: block; + width: 80%; +} + +div.refsynopsisdiv code.fieldsynopsis { + padding: 0; + border: 0; +} + +code.fieldsynopsis span.modifier { + min-width: 8em; + display: inline-block; +} + +code.fieldsynopsis span.type { + min-width: 11em; + display: inline-block; +} + +code.fieldsynopsis span.varname { + min-width: 11em; + display: inline-block; + font-size: 1.1em; + font-weight: bold; +} + +div.funcprototype-spacer { + max-height: 0.5em; +} + +table.funcprototype-table * td { + font-size: 0.9em; +} + +table.funcprototype-table * td code.funcdef { + font-size: 1.1em; +} + +b.fsfunc { + display: inline-block; + min-width: 11em; +}
\ No newline at end of file diff --git a/secret-service/org.freedesktop.Secrets.xml b/secret-service/org.freedesktop.Secrets.xml new file mode 100644 index 0000000..73c275b --- /dev/null +++ b/secret-service/org.freedesktop.Secrets.xml @@ -0,0 +1,427 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<!-- + * This is the well known dbus service name for controlling the + * entire daemon. The service manages collections of secrets. These + * are analogous to the gnome-keyring 'keyrings'. +--> +<tp:spec xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <tp:title>Secret Service API Specification</tp:title> + <tp:version>0.1</tp:version> + <tp:copyright> + Copyright (C) 2009 Stef Walter <stef@memberwebs.com> + </tp:copyright> + <tp:copyright> + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + </tp:copyright> + + <!-- + * ====================================================================================== + * ERROR CODES + * + --> + + <tp:errors namespace="org.freedesktop.Secret.Error"> + <tp:docstring>Errors returned by the Secret Service API.</tp:docstring> + <tp:error name="IsLocked"> + <tp:docstring>The object must be unlocked before this action can be carried out.</tp:docstring> + </tp:error> + <tp:error name="NoSession"> + <tp:docstring>The session does not exist.</tp:docstring> + </tp:error> + <tp:error name="NoSuchObject"> + <tp:docstring>No such item or collection exists.</tp:docstring> + </tp:error> + </tp:errors> + + <!-- + * ====================================================================================== + * SECRET STRUCT + * Signature: (oayay) + * + --> + + <tp:struct name="Secret"> + <tp:docstring>The Secret type holds a (possibly encoded) secret.</tp:docstring> + <tp:member type="o" name="session"> + <tp:docstring>The session that was used to encode the secret.</tp:docstring> + </tp:member> + <tp:member type="ay" name="parameters"> + <tp:docstring>Algorithm dependent parameters for secret value encoding.</tp:docstring> + </tp:member> + <tp:member type="ay" name="value"> + <tp:docstring>Possibly encoded secret value</tp:docstring> + </tp:member> + </tp:struct> + + <tp:mapping name="ObjectPath_Secret_Map"> + <tp:docstring>A mapping from object-paths to Secret structs</tp:docstring> + <tp:member type="o" name="Key"> + <tp:docstring>D-Bus object-path</tp:docstring> + </tp:member> + <tp:member type="(oayay)" name="Value" tp:type="Secret"> + <tp:docstring>A secret</tp:docstring> + </tp:member> + </tp:mapping> + + <!-- + * ====================================================================================== + * SERVICE INTERFACE + * + --> + + <node name="/org/freedesktop/Secrets"> + + <interface name="org.freedesktop.Secret.Service"> + + <tp:docstring> + The Secret Service manages all the sessions and collections. + </tp:docstring> + + <property name="Collections" type="ao" access="read"> + <tp:docstring>The object paths of all collections (ie: keyrings)</tp:docstring> + </property> + + <method name="OpenSession"> + <tp:docstring>Open a unique session for the caller application.</tp:docstring> + <arg name="algorithm" type="s" direction="in"> + <tp:docstring>The algorithm the caller wishes to use.</tp:docstring> + </arg> + <arg name="input" type="v" direction="in"> + <tp:docstring>Input arguments for the algorithm.</tp:docstring> + </arg> + <arg name="output" type="v" direction="out"> + <tp:docstring>Output of the session algorithm negotiation.</tp:docstring> + </arg> + <arg name="result" type="o" direction="out"> + <tp:docstring>The object path of the session, if session was created.</tp:docstring> + </arg> + </method> + + <method name="CreateCollection"> + <tp:docstring>Create a new collection with the specified properties.</tp:docstring> + <arg name="properties" type="a{sv}" direction="in"> + <tp:docstring>Properties for the new collection.</tp:docstring> + </arg> + <arg name="collection" type="o" direction="out"> + <tp:docstring>The new collection object, or '/' if prompting is necessary.</tp:docstring> + </arg> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt object if prompting is necessary, or '/' if no prompt was needed.</tp:docstring> + </arg> + </method> + + <method name="SearchItems"> + <tp:docstring>Find items in any collection.</tp:docstring> + <arg name="attributes" type="a{ss}" direction="in"> + <tp:docstring>Find secrets in any collection.</tp:docstring> + </arg> + <arg name="unlocked" type="ao" direction="out"> + <tp:docstring>Items found.</tp:docstring> + </arg> + <arg name="locked" type="ao" direction="out"> + <tp:docstring>Items found that require authentication.</tp:docstring> + </arg> + </method> + + <method name="Unlock"> + <tp:docstring>Unlock the specified objects.</tp:docstring> + <arg name="objects" type="ao" direction="in"> + <tp:docstring>Objects to unlock.</tp:docstring> + </arg> + <arg name="unlocked" type="ao" direction="out"> + <tp:docstring>Objects that were unlocked without a prompt.</tp:docstring> + </arg> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt object which can be used to unlock the remaining objects, or the special value '/' when no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="Lock"> + <tp:docstring>Lock the items.</tp:docstring> + <arg name="objects" type="ao" direction="in"> + <tp:docstring>Objects to lock.</tp:docstring> + </arg> + <arg name="locked" type="ao" direction="out"> + <tp:docstring>Objects that were locked without a prompt.</tp:docstring> + </arg> + <arg name="Prompt" type="o" direction="out"> + <tp:docstring>A prompt to lock the objects, or the special value '/' when no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="GetSecrets"> + <tp:docstring>Retrieve multiple secrets from different items.</tp:docstring> + <arg name="items" type="ao" direction="in"> + <tp:docstring>Items to get secrets for.</tp:docstring> + </arg> + <arg name="session" type="o" direction="in"> + <tp:docstring>The session to use to encode the secrets.</tp:docstring> + </arg> + <arg name="secrets" type="a{o(oayay)}" direction="out" tp:type="ObjectPath_Secret_Map"> + <tp:docstring>Secrets for the items.</tp:docstring> + </arg> + </method> + + <method name="ReadAlias"> + <tp:docstring>Get the collection with the given alias.</tp:docstring> + <arg name="name" type='s' direction='in'> + <tp:docstring>An alias, such as 'default'.</tp:docstring> + </arg> + <arg name="collection" type='o' direction='out'> + <tp:docstring>The collection or the the path '/' if no such collection exists.</tp:docstring> + </arg> + </method> + + <method name="SetAlias"> + <tp:docstring>Setup a collection alias.</tp:docstring> + <arg name="name" type='s' direction='in'> + <tp:docstring>An alias, such as 'default'.</tp:docstring> + </arg> + <arg name="collection" type='o' direction='in'> + <tp:docstring>The collection.</tp:docstring> + </arg> + </method> + + <signal name="CollectionCreated"> + <tp:docstring>A collection was created.</tp:docstring> + <arg name="collection" type="o"> + <tp:docstring>Collection that was created</tp:docstring> + </arg> + </signal> + + <signal name="CollectionDeleted"> + <tp:docstring>A collection was deleted.</tp:docstring> + <arg name="collection" type="o"> + <tp:docstring>Collection that was deleted.</tp:docstring> + </arg> + </signal> + + <signal name="CollectionChanged"> + <tp:docstring>A collection was changed.</tp:docstring> + <arg name="collection" type="o"> + <tp:docstring>Collection that was changed.</tp:docstring> + </arg> + </signal> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * COLLECTION INTERFACE + * + --> + + <node name="/org/freedesktop/Secrets/collection/xxxx"> + + <interface name="org.freedesktop.Secret.Collection"> + + <tp:docstring>A collection of items containing secrets.</tp:docstring> + + <property name="Items" type="ao" access="read"> + <tp:docstring>Items in this collection.</tp:docstring> + </property> + + <property name="Label" type="s" access="readwrite"> + <tp:docstring>The displayable label of this collection.</tp:docstring> + </property> + + <property name="Locked" type="s" access="read"> + <tp:docstring> + Whether the collection is locked and must be authenticated by the client application. + </tp:docstring> + </property> + + <property name="Created" type="t" access="read"> + <tp:docstring>The unix time when the collection was created.</tp:docstring> + </property> + + <property name="Modified" type="t" access="read"> + <tp:docstring>The unix time when the collection was last modified.</tp:docstring> + </property> + + <method name="Delete"> + <tp:docstring>Delete this collection.</tp:docstring> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt to delete the collection, or the special value '/' when no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="SearchItems"> + <tp:docstring>Search for items in this collection matching the lookup attributes.</tp:docstring> + <arg name="attributes" type="a{ss}" direction="in"> + <tp:docstring>Attributes to match.</tp:docstring> + </arg> + <arg name="results" type="ao" direction="out"> + <tp:docstring>Items that matched the attributes.</tp:docstring> + </arg> + </method> + + <method name="CreateItem"> + <tp:docstring>Create an item with the given attributes, secret and label. If replace is set, then it replaces an item already present with the same values for the attributes.</tp:docstring> + <arg name="properties" type="a{sv}" direction="in"> + <tp:docstring>The properties for the new item.</tp:docstring> + </arg> + <arg name="secret" type="(oayay)" tp:type="Secret" direction="in"> + <tp:docstring>The secret to store in the item, encoded with the included session.</tp:docstring> + </arg> + <arg name="replace" type="b" direction="in"> + <tp:docstring>Whether to replace an item with the same attributes or not.</tp:docstring> + </arg> + <arg name="item" type="o" direction="out"> + <tp:docstring>The item created, or the special value '/' if a prompt is necessary.</tp:docstring> + </arg> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt object, or the special value '/' if no prompt is necessary.</tp:docstring> + </arg> + </method> + + <signal name="ItemCreated"> + <tp:docstring>A new item in this collection was created.</tp:docstring> + <arg name="item" type="o"> + <tp:docstring>The item that was created.</tp:docstring> + </arg> + </signal> + + <signal name="ItemDeleted"> + <tp:docstring>An item in this collection was deleted.</tp:docstring> + + <arg name="item" type="o"> + <tp:docstring>The item that was deleted.</tp:docstring> + </arg> + </signal> + + <signal name="ItemChanged"> + <tp:docstring>An item in this collection changed.</tp:docstring> + + <arg name="item" type="o"> + <tp:docstring>The item that was changed.</tp:docstring> + </arg> + </signal> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * ITEM INTERFACE + * + --> + + <node name="/org/freedesktop/Secret/collection/xxxx/iiii"> + + <interface name="org.freedesktop.Secret.Item"> + + <tp:docstring>An item contains a secret, lookup attributes and has a label.</tp:docstring> + + <property name="Locked" type="b" access="read"> + <tp:docstring>Whether the item is locked and requires authentication, or not.</tp:docstring> + </property> + + <property name="Attributes" type="a{ss}" access="readwrite"> + <tp:docstring>The lookup attributes for this item.</tp:docstring> + </property> + + <property name="Label" type="s" access="readwrite"> + <tp:docstring>The displayable label for this item.</tp:docstring> + </property> + + <property name="Created" type="t" access="read"> + <tp:docstring>The unix time when the item was created.</tp:docstring> + </property> + + <property name="Modified" type="t" access="read"> + <tp:docstring>The unix time when the item was last modified.</tp:docstring> + </property> + + <method name="Delete"> + <tp:docstring>Delete this item.</tp:docstring> + <arg name="Prompt" type="o" direction="out"> + <tp:docstring>A prompt object, or the special value '/' if no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="GetSecret"> + <tp:docstring>Retrieve the secret for this item.</tp:docstring> + <arg name="session" type="o" direction="in"> + <tp:docstring>The session to use to encode the secret.</tp:docstring> + </arg> + <arg name="secret" type="(oayay)" tp:type="Secret" direction="out"> + <tp:docstring>The secret retrieved.</tp:docstring> + </arg> + </method> + + <method name="SetSecret"> + <tp:docstring>Set the secret for this item.</tp:docstring> + <arg name="secret" type="(oayay)" tp:type="Secret" direction="in"> + <tp:docstring>The secret to set, encoded for the included session.</tp:docstring> + </arg> + </method> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * SESSION INTERFACE + * + --> + + <node name="/org/freedesktop/Secret/session/ssss"> + + <interface name="org.freedesktop.Secret.Session"> + + <tp:docstring>A session tracks state between the service and a client application.</tp:docstring> + + <method name="Close"> + <tp:docstring>Close this session.</tp:docstring> + </method> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * PROMPT INTERFACE + * + --> + + <node name="/org/freedesktop/Secret/prompts/pppp"> + + <interface name="org.freedesktop.Secret.Prompt"> + <tp:docstring>A prompt necessary to complete an operation.</tp:docstring> + + <method name="Prompt"> + <tp:docstring>Perform the prompt.</tp:docstring> + <arg name="window-id" type="s" direction="in"> + <tp:docstring>Platform specific window handle to use for + showing the prompt.</tp:docstring> + </arg> + </method> + + <method name="Dismiss"> + <tp:docstring>Dismiss the prompt.</tp:docstring> + </method> + + <signal name="Completed"> + <tp:docstring>The prompt and operation completed.</tp:docstring> + <arg name="dismissed" type="b"> + <tp:docstring>Whether the prompt and operation were dismissed or not.</tp:docstring> + </arg> + <arg name="result" type="v"> + <tp:docstring>The possibly empty, operation specific, + result.</tp:docstring> + </arg> + </signal> + + </interface> + + </node> + +</tp:spec> diff --git a/secret-service/specification.xml b/secret-service/specification.xml new file mode 100644 index 0000000..9a9c81b --- /dev/null +++ b/secret-service/specification.xml @@ -0,0 +1,505 @@ +<?xml version="1.0"?> +<book xml:id="index" xmlns="http://docbook.org/ns/docbook" version="5.0"> + <bookinfo> + <title>Secrets Service API Draft</title> + <releaseinfo> + Secrets Service 0.1 DRAFT + </releaseinfo> + + <authorgroup> + <author> + <firstname>Stef</firstname> + <surname>Walter</surname> + <affiliation> + <jobtitle>GNOME Keyring Developer</jobtitle> + <address> + <email>stef@memberwebs.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Michael</firstname> + <surname>Leupold</surname> + <affiliation> + <jobtitle>KWallet Developer</jobtitle> + <address> + <email>lemma@confuego.org</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2008-2009</year> + <holder>The Secrets Service API Authors</holder> + </copyright> + + </bookinfo> + + <part xml:id="description"> + <title>API Documentation</title> + <chapter> + <title>Introduction</title> + + <para>The Secret Service API allows client applications to store secrets securely in a + service running in the user's login session. </para> + + <para>The secrets are usually stored in an encrypted manner by the service. The + service may need to be unlocked by the user before the secrets become available + for retrieval by client applications.</para> + + <para>The Secret Service stores a secret along with a set of lookup attributes. + The attributes can be used to lookup and retrieve a secret at a later date. The + lookup attributes are not treated as secret material, and the service may choose + to not encrypt attributes when storing them to disk.</para> + + <para>This API was desigened by GNOME and KDE developers with the goal of having + a common way to store secrets. Its predecessors are the desktop specific APIs + used by GNOME Keyring and KWallet.</para> + </chapter> + + <chapter> + <title>Secrets</title> + + <para>A secret is something an application wishes to store securely. A good example + is a password that an application needs to save and use at a later date.</para> + + <para>Within this API a secret value is treated as an array of bytes. It is + recommended that a secret consist of user readable text, although this API has + no such requirement.</para> + + <para>Applications wishing to store multiple values as part of a single secret, may + choose to use a textual format to combine these values into one. For example, the + 'desktop' key file format, or XML or another form of markup.</para> + + <para>Secrets may be <link linkend='transfer-secrets'>encrypted when transferred</link> + to the client application and vice versa.</para> + + <para>The <link linkend='type-Secret'><classname>Secret</classname> structure</link> encapsulates + a secret value along with its transfer encryption parameters.</para> + </chapter> + + <chapter> + <title>Collection and Items</title> + + <para>Each secret is stored together with + <link linkend='lookup-attributes'>lookup attributes</link> and a label. These together + form an <link linkend='org.freedesktop.Secret.Item'>item</link>.</para> + + <para>A group of items together form a + <link linkend='org.freedesktop.Secret.Collection'>collection</link>. + A collection is similar in concept to the terms 'keyring' or 'wallet'.</para> + + <para>Collections and items are represented as DBus objects, and each have their own + object paths. The object path of a collection or item should not change for its lifetime, + under normal circumstances.</para> + + <para>It is strongly recommended that client applications use + <link linkend='lookup-attributes'>lookup attributes</link> to find items rather than + recording the object path of a stored item. This allows maximum interoperability.</para> + + <para>An item or a collection may be initially in a locked state. When in a locked + state the item or collection may not be modified in any way, and the secret may not + be read. Client applications that require access to the secret of a locked item, or + desire to modify a locked item, should <link linkend='unlocking'>unlock it before use</link>.</para> + + <para>The service must prevent locked collections or items from modification. On + such an invalid access the + <link linkend='org.freedesktop.Secret.Error.IsLocked'><errorname>IsLocked</errorname></link> + error should be raised.</para> + + <para>Client applications without special requirements should store in the default + collection. The default collection is always accessible through a + <link linkend='object-paths'>specific object path</link>.</para> + + <para>A new item can be created with the + <link linkend='org.freedesktop.Secret.Collection.CreateItem'> + <function>CreateItem()</function></link> + method on the Collection interface. When creating an item, the properties of the new + item are specified. The service may ignore or change these properties when creating + the item.</para> + + <para>When creating an item, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the collection to be created. In this case, the + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object path of the new item.</para> + + <para>An item can be deleted by calling the + <link linkend='org.freedesktop.Secret.Item.Delete'><function>Delete()</function></link> + method on the Item interface.</para> + + <para>When deleting an item, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the item to be deleted.</para> + + <para>Client applications with special needs can create a new collection by calling the + <link linkend='org.freedesktop.Secret.Service.CreateCollection'> + <function>CreateCollection()</function></link> + method on the Service interface. When creating a collection, the properties of the new + collection are specified. The service may ignore or change these properties when creating + the collection.</para> + + <para>When creating a collection, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the collection to be created. In this case, the + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object path of the new collection.</para> + + <para>A collection can be deleted by calling the + <link linkend='org.freedesktop.Secret.Collection.Delete'><function>Delete()</function></link> + method on the Collection interface.</para> + + <para>When deleting a collection, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the collection to be deleted.</para> + + </chapter> + + <chapter xml:id="lookup-attributes"> + <title>Lookup Attributes</title> + + <para>Attributes can and should be stored with a secret to facilitate lookup + of the secret at a later date.</para> + + <para>An attribute constists of a name, and a value. Both parts are simple + strings.</para> + + <para>The service may have additional requirements as to what can be present + in an attribute name. It is recommended that attribute names are human + readable, and kept simple for the sake of simplicity.</para> + + <para>During a lookup, attribute names and values are matched via case-sensitive + string equality.</para> + + <para>It's important to remember that attributes are not part of the secret. + Services implementing this API will probably store attributes in an unencrypted + manner in order to support simple and effecient lookups.</para> + + <para>In order to search for items, use the + <link linkend='org.freedesktop.Secret.Service.SearchItems'><function>SearchItems()</function></link> + method of the Service interface. The matched items will be returned in two sets. The + <parameter class='function'>unlocked</parameter> return value will contain the object paths + of all the items that are not locked. The <parameter class='function'>locked</parameter> return + value will contain object paths of items that are locked, which can be + <link linkend='unlocking'>unlocked if desired</link>.</para> + + <para>The + <link linkend='org.freedesktop.Secret.Collection.SearchItems'><function>SearchItems()</function></link> + method of the Collection interface is similar, except for it only searches a single collection.</para> + + </chapter> + + <chapter xml:id="sessions"> + <title>Sessions</title> + + <para>A session is established between a client application and a service. A session + is used to <link linkend='transfer-secrets'>transfer secrets</link> between the client + application and the service.</para> + + <para>A session is established by calling the service's + <link linkend='org.freedesktop.Secret.Service.OpenSession'> + <function>OpenSession()</function></link> + method. Once established, a session is bound to calling application's connection to + the DBus session bus.</para> + + <para>A session is closed when the client application disconnects from the DBus + session bus. Alternatively the client application can call the + <link linkend='org.freedesktop.Secret.Session.Close'><function>Close()</function></link> + method on the session interface. Once a session is closed all session specific + negotiations will be dropped by the service.</para> + + <para>More than one session may opened by a client application, although this is + not normally necessary.</para> + </chapter> + + <chapter xml:id='transfer-secrets'> + <title>Transfer of Secrets</title> + + <para>To access or store secrets, use the + <link linkend='org.freedesktop.Secret.Item.GetSecret'><function>GetSecret()</function></link>, + <link linkend='org.freedesktop.Secret.Item.SetSecret'><function>SetSecret()</function></link> + methods on the item interface, or the + <link linkend='org.freedesktop.Secret.Service.GetSecrets'><function>GetSecrets()</function></link>, + method on the service interface.</para> + + <para>You must specify a session when retrieving or storing a secret. The session + controls how the secret is encoded during transfer. Since this is a D-Bus API, the + data in all method calls and other accesses in this API will go through multiple + processes, and may be cached arbitrarilyby the OS or elsewhere.</para> + + <para>The Secrets API has provision to encrypt secrets while in transit between + the service and the client application. The encryption is not envisioned to withstand + man in the middle attacks, or other active attacks. It is envisioned to minimize + storage of plain text secrets in memory and prevent storage plain text storage of + secrets in a swap file or other caching mechanism.</para> + + <para>Many client applications may choose not to make use of the provisions to + encrypt secrets in transit. In fact for applications unable to prevent their own + memory from being paged to disk (eg: Java, C# or Python apps), transfering + encrypted secrets would be an excersize of questionable value.</para> + + <section> + <title>Negotiation of Algorithms</title> + + <para>In order to encrypt secrets in transit, the service and the client + application must agree on an algorithm, and some algorithm specific + parameters (eg: a key).</para> + + <para>When the client application opens a <link linkend='sessions'>session</link> + with the service, it calls the + <link linkend='org.freedesktop.Secret.Service.OpenSession'><function> + OpenSession()</function></link> method on the service. The algorithms argument to the + <function>OpenSession()</function> method specifies a set of algorithms to be used + together for key agreement and encryption. The other arguments are algorithm + specific.</para> + + <para>If a service does not support a specific set of algorithms, a + <errorname>org.freedesktop.DBus.Error.NotSupported</errorname> + error is returned, and the client is free to try another set of algorithms. + The <emphasis>plain</emphasis> algorithm is almost always supported.</para> + + <para>An algorithm may require that the <function>OpenSession()</function> method is + called multiple times in succession to be complete. Each iteration transfers + algorithm specific data back forth between the service and the client. The object path + '/' is returned from <function>OpenSession()</function> when session negotiation is + incomplete.</para> + + <para>None of the algorithms documented in this initial version of the specification + require multiple calls to <function>OpenSession()</function>.</para> + + <para>When <function>OpenSession()</function> completes, it returns the session object + path along with a valid session object path.</para> + + <para>Once an session algorithm has been negotiated, it is used for all transfer a + secrets whenever that session is specified along with the + <link linkend='type-Secret'><classname>secret</classname></link>.</para> + </section> + + <section> + <title>Algorithm: plain</title> + + <segmentedlist> + <?dbhtml list-presentation="list"?> + <segtitle>Session algorithm</segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session input</link></segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session output</link></segtitle> + <segtitle><link linkend='type-Secret'> + <classname>Secret</classname> parameter</link></segtitle> + <seglistitem> + <!-- TODO: literal? --> + <seg><emphasis>plain</emphasis></seg> + <seg>empty string</seg> + <seg>empty string</seg> + <seg>empty string</seg> + </seglistitem> + </segmentedlist> + + <para>The plain algorithm does no encryption whatsoever.</para> + + <para>It is strongly recommended that a service implementing this API support + the <emphasis>plain</emphasis> algorithm.</para> + </section> + + <section> + <title>Algorithm: dh-ietf1024-aes128-cbc-pkcs7</title> + + <segmentedlist> + <?dbhtml list-presentation="list"?> + <segtitle>Session algorithm</segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session input</link></segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session output</link></segtitle> + <segtitle><link linkend='type-Secret'> + <classname>Secret</classname> parameter</link></segtitle> + <seglistitem> + <!-- TODO: literal? --> + <seg><emphasis>dh-ietf1024-aes128-cbc-pkcs7</emphasis></seg> + <seg>Client DH pub key as an array of bytes</seg> + <seg>Service DH pub key as an array of bytes</seg> + <seg>16 byte AES initialization vector</seg> + </seglistitem> + </segmentedlist> + + <para>The public keys are transferred as an array of bytes representing an + unsigned integer of arbitrary size, most-significant byte first (e.g., the + integer 32768 is represented as the 2-byte string 0x80 0x00)</para> + </section> + + </chapter> + + <chapter xml:id='unlocking'> + <title>Locking and Unlocking</title> + + <para>Some items and/or collections may be marked as locked by the service. + The secrets of locked items cannot be accessed. Additionally, locked items or collections + cannot be modified by the client application.</para> + + <para>It's up to the service whether to unlock items individually, or collections as a + whole. The client application should act as if it must unlock each item individually.</para> + + <para>A service may upon unlocking a collection, unlock all items in that collection. If + a service is not able to unlock an item individually, it should treat a request to unlock + an item as a request to unlock the connection that the item is in.</para> + + <para>A service may choose to unlock items or collections just for a single client + application. Alternatively the service may choose to allow any client application to access + items or collections unlocked by a another client application.</para> + + <para>A client application should always be ready to unlock the items for the secrets + it needs, or objects it must modify. It must not assume that an item is already unlocked + for whatever reason.</para> + + <para>A service may lock previously unlocked items for any reason at any time. Usually this + is done in response to user actions, timeouts, or external actions (such as the computer + sleeping). The inherent race conditions present due to this are unavoidable, and must be + handled gracefully.</para> + + <para>In order to unlock an item or collection the service's + <link linkend='org.freedesktop.Secret.Service.Unlock'> + <function>Unlock()</function></link> + method is called with one or more DBus object paths of items or collections. The + <function>Unlock()</function> will return the DBus object paths of objects it could + immediately unlock without prompting.</para> + + <para>The <function>Unlock()</function> method may also return a + <link linkend='org.freedesktop.Secret.Prompt.Prompt'>prompt object</link>. If a prompt + object is returned, it must be <link linkend='prompts'>acted upon</link> in order to complete + the unlocking of the remaining objects. The + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object paths that were successfully unlocked by the prompt.</para> + + <para>In order to lock an item or collection the service's + <link linkend='org.freedesktop.Secret.Service.Unlock'> + <function>Lock()</function></link> + method is called with one or more DBus object paths of items or collections. The + <function>Lock()</function> will return the DBus object paths of objects it could + immediately lock without prompting.</para> + + <para>The <function>Lock()</function> method may also return a + <link linkend='org.freedesktop.Secret.Prompt.Prompt'>prompt object</link>. If a prompt + object is returned, it must be <link linkend='prompts'>acted upon</link> in order to complete + the locking of the remaining objects. The + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object paths that were successfully locked by the prompt.</para> + </chapter> + + <chapter xml:id='prompts'> + <title>Prompts and Prompting</title> + + <para>In order to complete various operations, such as unlocking a collection, the + service may need to prompt the user for additional information, such as a master password.</para> + + <para>The prompts are displayed by the service on behalf of the client application.</para> + + <para>Operations that require a prompt to complete will return a prompt object. The client + application must then call the + <link linkend='org.freedesktop.Secret.Prompt.Prompt'><function>Prompt()</function></link> + method of the prompt object to display the prompt. Client applications can use the + <parameter class='function'>window-id</parameter> + argument to display the prompt attached to their application window.</para> + + <para>Once the user provides the additional required information to the prompt, the service + completes the operation that required the prompt. Then it emits the the + <link linkend='org.freedesktop.Secret.Prompt.Completed'><function>Completed</function></link> + signal of the prompt object. The <parameter class='function'>result</parameter> argument of + the signal contains operation an operation specific result.</para> + + <para>Either the user or the client application can dismiss a prompt. In this case the + operation that required the additional information is cancelled. The client application + can dismiss a prompt by calling the + <link linkend='org.freedesktop.Secret.Prompt.Dismiss'><function>Dismiss()</function></link> + method of the prompt object. The <function>Completed</function> signal will be emitted + with its <parameter class='function'>dismissed</parameter> argument set to + <constant>TRUE</constant>.</para> + + <para>Once the <function>Completed</function> signal is emitted on a prompt object, it + is no longer valid. Prompt objects are specific to the client application's connection + to the DBus bus. Once an application disconnects, all its prompts are no longer valid.</para> + + <para>There is an inherent race between the <function>Dismiss()</function> method and the + <function>Completed</function> signal. An application calling <function>Dismiss()</function> + must be prepared to handle the fact that the <function>Completed</function> has already been + emitted (although perhaps not received by the client). In addition the client must be prepared + to handle the fact that the prompt object is no longer valid.</para> + </chapter> + + <chapter> + <title>What's not included in the API</title> + + <para>A service may implement additional DBus interfaces for further capabilities not + included in this specification. Password management applications or other narrowly + focused tools should make use of these when necessary.</para> + + <para>This specification does not mandate the use of master passwords to lock a + collection of secrets. The service may choose to implement any method for locking + secrets.</para> + + <para>This specification does not mandate any form of access control. The service may + choose to allow certain applications to access a keyring, and others.</para> + + <para>[TODO: complete]</para> + </chapter> + + <chapter> + <title>Notes for Service Implementors</title> + + <para>[TODO: complete]</para> + </chapter> + + </part> + + <part xml:id="ref-dbus-api"> + <title>D-Bus API Reference</title> + + <chapter xml:id='object-paths'> + <title>Object Paths</title> + + <para>The various DBus object paths used with the Secret Service API are designed to be human + readable but not displayed to the user. The object path of an item or collection should + not change for its lifetime, under normal circumstances.</para> + + <programlisting>/org/freedesktop/secrets</programlisting> + <para>The object path for the service.</para> + + <programlisting>/org/freedesktop/secrets/collection/<emphasis>xxxx</emphasis></programlisting> + <para>The object path for a collection, where <emphasis>xxxx</emphasis> represents a + possibly encoded or truncated version of the initial label of the collection.</para> + + <programlisting>/org/freedesktop/secrets/collection/<emphasis>xxxx</emphasis>/<emphasis>iiii</emphasis></programlisting> + <para>The object path for an item, where <emphasis>xxxx</emphasis> is the collection (above) + and <emphasis>iiii</emphasis> is an auto-generated item specific identifier.</para> + + <programlisting>/org/freedesktop/secrets/session/<emphasis>ssss</emphasis></programlisting> + <para>The object path for a session, where <emphasis>ssss</emphasis> is an auto-generated + session specific identifier.</para> + + <programlisting>/org/freedesktop/secrets/aliases/default</programlisting> + <para>The default collection for client applications to store secrets is available under + this object path in addition to its real object path (above). Other aliases may also be + present.</para> + </chapter> + + <xi:include href="reference.xml" xpointer="interfaces" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + <xi:include href="reference.xml" xpointer="types" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + <xi:include href="reference.xml" xpointer="errors" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + + </part> + + <xi:include href="xml/annotation-glossary.xml" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> +</book> diff --git a/secret-service/tools/resolve-type.xsl b/secret-service/tools/resolve-type.xsl new file mode 100644 index 0000000..a37f2af --- /dev/null +++ b/secret-service/tools/resolve-type.xsl @@ -0,0 +1,122 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:html="http://www.w3.org/1999/xhtml" + exclude-result-prefixes="tp html"> + +<!-- + Helper templates for Telepathy D-Bus Introspection conversion. + + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +--> + + <!-- Resolve the type a node has. This will first look at tp:type and + - if not found - use the type attribute --> + <xsl:template name="ResolveType"> + <xsl:param name="node"/> + <xsl:variable name="unstripped"> + <xsl:choose> + <xsl:when test="$node//@tp:type"> + <xsl:call-template name="TpType"> + <xsl:with-param name="type" select="$node//@tp:type"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="$node//@type"> + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="$node//@type"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + Node doesn't contain a type. + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:value-of select="translate(translate($unstripped, ' ', ''), '
', '')"/> + </xsl:template> + + <!-- Map a D-Bus type to its EggDBus counterpart --> + <xsl:template name="DBusType"> + <xsl:param name="type"/> + <xsl:choose> + <xsl:when test="$type='o'">ObjectPath</xsl:when> + <xsl:when test="$type='s'">String</xsl:when> + <xsl:when test="$type='y'">Byte</xsl:when> + <xsl:when test="$type='b'">Boolean</xsl:when> + <xsl:when test="$type='n'">Int16</xsl:when> + <xsl:when test="$type='q'">UInt16</xsl:when> + <xsl:when test="$type='i'">Int32</xsl:when> + <xsl:when test="$type='u'">UInt32</xsl:when> + <xsl:when test="$type='x'">Int64</xsl:when> + <xsl:when test="$type='t'">UInt64</xsl:when> + <xsl:when test="$type='d'">Double</xsl:when> + <xsl:when test="$type='g'">Signature</xsl:when> + <xsl:when test="$type='v'">Variant</xsl:when> + <xsl:when test="starts-with($type, 'a{')"> + Dict< + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="substring($type, 3, 1)"/> + </xsl:call-template> + , + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="substring($type, 4, 1)"/> + </xsl:call-template> + > + </xsl:when> + <xsl:when test="starts-with($type, 'a')"> + Array< + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="substring($type, 2)"/> + </xsl:call-template> + > + </xsl:when> + <!-- TODO: doesn't implement dict-entries and structs --> + <xsl:otherwise> + <xsl:message terminate="yes"> + Unknown DBus Type <xsl:value-of select="$type"/> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Resolve tp:type attributes by searching for matching tp:struct + and tp:mapping elements --> + <xsl:template name="TpType"> + <xsl:param name="type"/> + <xsl:choose> + <xsl:when test="/tp:spec/tp:struct[@name=$type]"> + <xsl:value-of select="$type"/> + </xsl:when> + <xsl:when test="/tp:spec/tp:mapping[@name=$type]"> + Dict< + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="/tp:spec/tp:mapping[@name=$type]/tp:member[@name='Key']"/> + </xsl:call-template>, + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="/tp:spec/tp:mapping[@name=$type]/tp:member[@name='Value']"/> + </xsl:call-template> + > + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + Unspecified type <xsl:value-of select="$type"/>. + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> +</xsl:stylesheet> diff --git a/secret-service/tools/spec-to-docbook.xsl b/secret-service/tools/spec-to-docbook.xsl new file mode 100644 index 0000000..14d5b24 --- /dev/null +++ b/secret-service/tools/spec-to-docbook.xsl @@ -0,0 +1,1239 @@ +<?xml version="1.0"?> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:docbook="http://docbook.org/ns/docbook" + exclude-result-prefixes="tp html"> + +<!-- + Telepathy D-Bus Introspection to Docbook XML translator. + Based on Telepathy's doc-generator.xsl. + + Copyright (C) 2006-2008 Collabora Limited + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +--> + + <xsl:output method="xml" indent="yes" encoding="ascii" + omit-xml-declaration="no"/> + + <xsl:include href="resolve-type.xsl"/> + + <xsl:param name="allow-undefined-interfaces" select="false()"/> + + <xsl:template match="docbook:* | html:* | @*"> + <xsl:copy> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <xsl:template name="direction"> + <xsl:param name="indirection"/> + <xsl:choose> + <xsl:when test="$indirection = 'in'">IN</xsl:when> + <xsl:otherwise>OUT</xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="tp:type"> + <xsl:call-template name="tp-type"> + <xsl:with-param name="tp-type" select="string(.)"/> + </xsl:call-template> + </xsl:template> + + <!-- tp:dbus-ref: reference a D-Bus interface, signal, method or property --> + <xsl:template match="tp:dbus-ref"> + <xsl:variable name="name"> + <xsl:choose> + <xsl:when test="@namespace"> + <xsl:value-of select="@namespace"/> + <xsl:text>.</xsl:text> + </xsl:when> + </xsl:choose> + <xsl:value-of select="string(.)"/> + </xsl:variable> + + <xsl:choose> + <xsl:when test="//interface[@name=$name] + or //interface/method[concat(../@name, '.', @name)=$name] + or //interface/signal[concat(../@name, '.', @name)=$name] + or //interface/property[concat(../@name, '.', @name)=$name] + or //interface[@name=concat($name, '.DRAFT')] + or //interface/method[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/signal[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/property[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + "> + <link linkend="{$name}"> + <literal><xsl:value-of select="$name"/></literal> + </link> + </xsl:when> + + <xsl:when test="$allow-undefined-interfaces"> + <!-- TODO: Convert to docbook --> + <span xmlns="http://www.w3.org/1999/xhtml" title="defined elsewhere"> + <xsl:value-of select="string(.)"/> + </span> + </xsl:when> + + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: cannot find D-Bus interface, method, </xsl:text> + <xsl:text>signal or property called '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- tp:member-ref: reference a property of the current interface --> + <xsl:template match="tp:member-ref"> + <xsl:variable name="prefix" select="concat(ancestor::interface/@name, + '.')"/> + <xsl:variable name="name" select="string(.)"/> + + <xsl:if test="not(ancestor::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: Cannot use tp:member-ref when not in an</xsl:text> + <xsl:text> <interface> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:choose> + <xsl:when test="ancestor::interface/signal[@name=$name]"/> + <xsl:when test="ancestor::interface/method[@name=$name]"/> + <xsl:when test="ancestor::interface/property[@name=$name]"/> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: interface </xsl:text> + <xsl:value-of select="ancestor::interface/@name"/> + <xsl:text> has no signal/method/property called </xsl:text> + <xsl:value-of select="$name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + + <link linkend="{$prefix}{$name}"> + <literal><xsl:value-of select="concat($prefix, $name)"/></literal> + </link> + </xsl:template> + + <xsl:template match="*" mode="identity"> + <xsl:copy> + <xsl:apply-templates mode="identity"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="tp:docstring"> + <para> + <xsl:copy-of select="child::node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:docstring" mode="nopara"> + <xsl:copy-of select="child::node()"/> + </xsl:template> + + <xsl:template match="tp:added"> + <para> + Added in version <xsl:value-of select="@version"/>. + <xsl:apply-templates select="node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:changed"> + <xsl:choose> + <xsl:when test="node()"> + <para> + Changed in version <xsl:value-of select="@version"/>: + <xsl:apply-templates select="node()"/></para> + </xsl:when> + <xsl:otherwise> + <para>Changed in version + <xsl:value-of select="@version"/></para> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="tp:deprecated"> + <para> + Deprecated since version <xsl:value-of select="@version"/>. + <xsl:apply-templates select="node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:rationale"> + <!-- TODO: special? --> + <para> + <xsl:apply-templates select="node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:errors"> + <title>Errors</title> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template name="generic-types"> + <chapter> + <xsl:attribute name="xml:id">types</xsl:attribute> + <title>Types</title> + <xsl:call-template name="do-types"/> + </chapter> + </xsl:template> + + <xsl:template name="do-types"> + <xsl:if test="tp:simple-type"> + <section> + <title>Simple types</title> + <xsl:apply-templates select="tp:simple-type"/> + </section> + </xsl:if> + + <xsl:if test="tp:enum"> + <section> + <title>Enumerated types</title> + <xsl:apply-templates select="tp:enum"/> + </section> + </xsl:if> + + <xsl:if test="tp:flags"> + <section> + <title>Sets of flags</title> + <xsl:apply-templates select="tp:flags"/> + </section> + </xsl:if> + + <xsl:if test="tp:struct"> + <section> + <title>Struct types</title> + <xsl:apply-templates select="tp:struct"/> + </section> + </xsl:if> + + <xsl:if test="tp:mapping"> + <section> + <title>Map types</title> + <xsl:apply-templates select="tp:mapping"/> + </section> + </xsl:if> + + <xsl:if test="tp:external-type"> + <section> + <title>Types defined elsewhere</title> + <glosslist> + <xsl:apply-templates select="tp:external-type"/> + </glosslist> + </section> + </xsl:if> + </xsl:template> + + <xsl:template match="tp:error"> + <simplesect> + <title> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/> + </xsl:attribute> + <literal><xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/></literal> + </title> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </simplesect> + </xsl:template> + + <xsl:template match="/tp:spec/tp:copyright"> + <!-- TODO: use <copyright> --> + <legalnotice> + <para><xsl:apply-templates mode="text"/></para> + </legalnotice> + </xsl:template> + <xsl:template match="/tp:spec/tp:license"> + <!-- TODO: right tag? --> + <legalnotice> + <para> + <xsl:apply-templates/> + </para> + </legalnotice> + </xsl:template> + + <xsl:template match="tp:copyright"/> + <xsl:template match="tp:license"/> + + <xsl:template match="interface"> + + <refentry> + <xsl:attribute name="xml:id"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <refmeta> + <refentrytitle><literal><xsl:value-of select="@name"/></literal></refentrytitle> + </refmeta> + + <refnamediv> + <refdescriptor><xsl:value-of select="@name"/></refdescriptor> + <refname><xsl:value-of select="@name"/></refname> + <refpurpose><xsl:apply-templates select="tp:docstring" mode="nopara"/></refpurpose> + </refnamediv> + + <xsl:if test="tp:added"> + <refsection> + <xsl:apply-templates select="tp:added"/> + </refsection> + </xsl:if> + <xsl:if test="tp:changed"> + <refsection> + <xsl:apply-templates select="tp:changed"/> + </refsection> + </xsl:if> + <xsl:if test="tp:deprecated"> + <refsection> + <xsl:apply-templates select="tp:deprecated"/> + </refsection> + </xsl:if> + + <xsl:if test="@tp:causes-havoc"> + <refsection> + <warning> + <para> + This interface is <xsl:value-of select="@tp:causes-havoc"/> + and is likely to cause havoc to your API/ABI if bindings are generated. + Don't include it in libraries that care about compatibility. + </para> + </warning> + </refsection> + </xsl:if> + + <xsl:if test="tp:requires"> + <refsection> + <tip> + <para>Implementations of this interface must also implement:</para> + <itemizedlist> + <xsl:for-each select="tp:requires"> + <listitem> + <para> + <link linkend="{@interface}"> + <literal><xsl:value-of select="@interface"/></literal> + </link> + </para> + </listitem> + </xsl:for-each> + </itemizedlist> + </tip> + </refsection> + </xsl:if> + + <refsynopsisdiv> + <xsl:if test="method"> + <refsect2> + <title>Methods</title> + <funcsynopsis> + <xsl:apply-templates select="method" mode="funcsynopsislinked"/> + </funcsynopsis> + </refsect2> + </xsl:if> + <xsl:if test="signal"> + <refsect2> + <title>Signals</title> + <funcsynopsis> + <xsl:apply-templates select="signal" mode="funcsynopsislinked"/> + </funcsynopsis> + </refsect2> + </xsl:if> + <xsl:if test="property"> + <refsect2> + <title>Properties</title> + <refsynopsisdiv> + <title> </title> + <xsl:apply-templates select="property" mode="fieldsynopsislinked"/> + </refsynopsisdiv> + </refsect2> + </xsl:if> + </refsynopsisdiv> + + <xsl:if test="method"> + <refsection> + <title>Methods</title> + <xsl:apply-templates select="method" mode="detail"/> + </refsection> + </xsl:if> + + <xsl:if test="signal"> + <refsection> + <title>Signals</title> + <xsl:apply-templates select="signal" mode="detail"/> + </refsection> + </xsl:if> + + <xsl:if test="tp:property"> + <refsection> + <title>Telepathy Properties</title> + <para> + Accessed using the + <link linkend="org.freedesktop.Telepathy.Properties"> + <literal>org.freedesktop.Telepathy.Properties</literal> + </link> + </para> + <glosslist> + <xsl:apply-templates select="tp:property" mode="detail"/> + </glosslist> + </refsection> + </xsl:if> + + <xsl:if test="property"> + <refsection> + <title>D-Bus Properties</title> + <para> + Accessed using the org.freedesktop.DBus.Properties interface. + </para> + <xsl:apply-templates select="property" mode="detail"/> + </refsection> + </xsl:if> + + <xsl:call-template name="do-types"/> + + </refentry> + + </xsl:template> + + <xsl:template match="tp:flags"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:flags type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:flags type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <title><literal><xsl:value-of select="@name"/></literal></title> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <glosslist> + <xsl:variable name="value-prefix"> + <xsl:choose> + <xsl:when test="@value-prefix"> + <xsl:value-of select="@value-prefix"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:for-each select="tp:flag"> + <glossentry> + <glossterm> + <xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/> + </glossterm> + <glossdef> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:when> + <xsl:otherwise> + (Undocumented) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:for-each> + </glosslist> + </section> + </xsl:template> + + <xsl:template match="tp:enum"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:enum type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:enum type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title><literal><xsl:value-of select="@name"/></literal></title> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <glosslist> + <xsl:variable name="value-prefix"> + <xsl:choose> + <xsl:when test="@value-prefix"> + <xsl:value-of select="@value-prefix"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:for-each select="tp:enumvalue"> + <glossentry> + <glossterm> + <xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/> + </glossterm> + <glossdef> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:when> + <xsl:otherwise> + (Undocumented) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:for-each> + </glosslist> + </section> + </xsl:template> + + <xsl:template match="property" mode="fieldsynopsis"> + + <fieldsynopsis> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@name, '.', @name)"/> + </xsl:attribute> + <modifier> + <xsl:choose> + <xsl:when test="@access = 'read'"> + <xsl:text>READ</xsl:text> + </xsl:when> + <xsl:when test="@access = 'write'"> + <xsl:text>WRITE</xsl:text> + </xsl:when> + <xsl:when test="@access = 'readwrite'"> + <xsl:text>READWRITE</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: unknown or missing value for </xsl:text> + <xsl:text>@access on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </modifier> + <type> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </type> + <varname> + <xsl:value-of select="@name"/> + </varname> + </fieldsynopsis> + + </xsl:template> + + <xsl:template match="property" mode="fieldsynopsislinked"> + + <fieldsynopsis> + <modifier> + <xsl:choose> + <xsl:when test="@access = 'read'"> + <xsl:text>READ</xsl:text> + </xsl:when> + <xsl:when test="@access = 'write'"> + <xsl:text>WRITE</xsl:text> + </xsl:when> + <xsl:when test="@access = 'readwrite'"> + <xsl:text>READWRITE</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: unknown or missing value for </xsl:text> + <xsl:text>@access on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </modifier> + <type> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </type> + <varname> + <xsl:attribute name="xlink:href"> + <xsl:value-of select="concat('#', ../@name, '.', @name)"/> + </xsl:attribute> + <xsl:value-of select="@name"/> + </varname> + </fieldsynopsis> + + </xsl:template> + + <xsl:template match="property" mode="detail"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: property </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a property of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:apply-templates select="." mode="fieldsynopsis"/> + + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:template> + + <xsl:template match="tp:property" mode="detail"> + <glossentry> + <glossterm> + <xsl:if test="@name"> + <xsl:value-of select="@name"/> − + </xsl:if> + <xsl:value-of select="@type"/> + </glossterm> + <glossdef> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="tp:mapping"> + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="@name"/></literal> + </title> + <xsl:apply-templates select="tp:docstring"/> + <xsl:if test="string(@array-name) != ''"> + <para> + In bindings that need a separate name, arrays of + <xsl:value-of select="@name"/> should be called + <xsl:value-of select="@array-name"/>. + </para> + </xsl:if> + <section> + <title>Members</title> + <glosslist> + <xsl:apply-templates select="tp:member" mode="description"/> + </glosslist> + </section> + </section> + </xsl:template> + + <xsl:template match="tp:docstring" mode="in-index"/> + + <xsl:template match="tp:simple-type | tp:enum | tp:flags | tp:external-type" + mode="in-index"> + − <xsl:value-of select="@type"/> + </xsl:template> + + <xsl:template match="tp:simple-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:simple-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:simple-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="@name"/> − <xsl:value-of select="@type"/></literal> + </title> + <para> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </para> + </section> + </xsl:template> + + <xsl:template match="tp:external-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:external-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:external-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <glossentry> + <glossterm> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <xsl:value-of select="@name"/> − <xsl:value-of select="@type"/> + </glossterm> + <glossdef>Defined by: <xsl:value-of select="@from"/></glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="tp:struct" mode="in-index"> + − ( <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> ) + </xsl:template> + + <xsl:template match="tp:mapping" mode="in-index"> + − a{ <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()"> → </xsl:if> + </xsl:for-each> } + </xsl:template> + + <xsl:template match="tp:struct"> + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title> + <literal> + <xsl:value-of select="@name"/> + </literal> + </title> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <xsl:choose> + <xsl:when test="string(@array-name) != ''"> + <para>In bindings that need a separate name, arrays of + <xsl:value-of select="@name"/> should be called + <xsl:value-of select="@array-name"/>.</para> + </xsl:when> + <xsl:otherwise> + <para>Arrays of <xsl:value-of select="@name"/> don't generally + make sense.</para> + </xsl:otherwise> + </xsl:choose> + <classsynopsis> + <ooclass> + <modifier>struct</modifier> + <classname><xsl:value-of select="@name"/></classname> + </ooclass> + <xsl:apply-templates select="tp:member" mode="fieldsynopsis"/> + </classsynopsis> + <glosslist> + <xsl:apply-templates select="tp:member" mode="description"/> + </glosslist> + </section> + </xsl:template> + + <xsl:template match="arg" mode="paramdef"> + <paramdef> + <xsl:call-template name="direction"> + <xsl:with-param name="indirection" select="@direction"/> + </xsl:call-template> + <xsl:text> </xsl:text> + <type> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </type> + <xsl:text> </xsl:text> + <parameter><xsl:value-of select="@name"/></parameter> + </paramdef> + </xsl:template> + + <xsl:template match="arg" mode="paramtable"> + <glossentry> + <glossterm><literal><xsl:value-of select="@name"/></literal></glossterm> + <glossdef> + <para><xsl:apply-templates select="tp:docstring" mode="nopara"/></para> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="method|signal" mode="funcsynopsis"> + <funcsynopsis> + <funcprototype> + <funcdef> + <function> + <xsl:value-of select="@name"/> + </function> + </funcdef> + <xsl:choose> + <xsl:when test="arg"> + <xsl:apply-templates select="arg" mode="paramdef"/> + </xsl:when> + <xsl:otherwise> + <void/> + </xsl:otherwise> + </xsl:choose> + </funcprototype> + </funcsynopsis> + </xsl:template> + + <xsl:template match="method|signal" mode="funcsynopsislinked"> + <funcprototype> + <funcdef> + <function linkend="{concat(parent::interface//@name, '.', @name)}"> + <xsl:value-of select="@name"/> + </function> + </funcdef> + <xsl:choose> + <xsl:when test="arg"> + <xsl:apply-templates select="arg" mode="paramdef"/> + </xsl:when> + <xsl:otherwise> + <void/> + </xsl:otherwise> + </xsl:choose> + </funcprototype> + </xsl:template> + + <xsl:template match="method" mode="detail"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: method </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a method of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="@direction='in'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an 'in' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:when test="@direction='out'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="no"> + <xsl:text>INFO: an 'out' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction neither 'in' nor 'out'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + + <refsection> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@name, concat('.', @name))"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="concat(../@name, concat('.', @name))"/></literal> + </title> + <xsl:apply-templates select="." mode="funcsynopsis"/> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + + <xsl:if test="arg"> + <glosslist> + <xsl:apply-templates select="arg" mode="paramtable"/> + </glosslist> + </xsl:if> + + <xsl:if test="tp:possible-errors"> + <formalpara> + <title>Possible errors</title> + <para> + <glosslist> + <xsl:apply-templates select="tp:possible-errors/tp:error"/> + </glosslist> + </para> + </formalpara> + </xsl:if> + </refsection> + </xsl:template> + + <xsl:template name="tp-type"> + <xsl:param name="tp-type"/> + <xsl:param name="type"/> + + <xsl:variable name="single-type"> + <xsl:choose> + <xsl:when test="contains($tp-type, '[]')"> + <xsl:value-of select="substring-before($tp-type, '[]')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tp-type"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="type-of-tp-type"> + <xsl:if test="contains($tp-type, '[]')"> + <!-- one 'a', plus one for each [ after the [], and delete all ] --> + <xsl:value-of select="concat('a', + translate(substring-after($tp-type, '[]'), '[]', 'a'))"/> + </xsl:if> + + <xsl:choose> + <xsl:when test="//tp:simple-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:simple-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:struct[@name=$single-type]"> + <xsl:text>(</xsl:text> + <xsl:for-each select="//tp:struct[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>)</xsl:text> + </xsl:when> + <xsl:when test="//tp:enum[@name=$single-type]"> + <xsl:value-of select="string(//tp:enum[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:flags[@name=$single-type]"> + <xsl:value-of select="string(//tp:flags[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:mapping[@name=$single-type]"> + <xsl:text>a{</xsl:text> + <xsl:for-each select="//tp:mapping[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>}</xsl:text> + </xsl:when> + <xsl:when test="//tp:external-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:external-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: Unable to find type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:if test="string($type) != '' and + string($type-of-tp-type) != string($type)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: tp:type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' has D-Bus type '</xsl:text> + <xsl:value-of select="$type-of-tp-type"/> + <xsl:text>' but has been used with type='</xsl:text> + <xsl:value-of select="$type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + + <link linkend="type-{$single-type}"> + <literal><xsl:value-of select="concat('type-', $single-type)"/></literal> + </link> + + </xsl:template> + + <xsl:template name="parenthesized-tp-type"> + <xsl:if test="@tp:type"> + <xsl:text> (</xsl:text> + <xsl:call-template name="tp-type"> + <xsl:with-param name="tp-type" select="@tp:type"/> + <xsl:with-param name="type" select="@type"/> + </xsl:call-template> + <xsl:text>)</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="tp:member" mode="fieldsynopsis"> + <xsl:variable name="type"> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:variable> + <fieldsynopsis> + <type><xsl:value-of select="normalize-space($type)"/></type> + <varname><xsl:value-of select="@name"/></varname> + </fieldsynopsis> + </xsl:template> + + <xsl:template match="tp:member" mode="description"> + <glossentry> + <glossterm> + <varname><xsl:value-of select="@name"/></varname> + </glossterm> + <glossdef> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + </xsl:when> + <xsl:otherwise> + <!-- emphasize --> + (undocumented) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="tp:possible-errors/tp:error"> + <glossentry> + <glossterm> + <xsl:value-of select="@name"/> + </glossterm> + <glossdef> + <xsl:variable name="name" select="@name"/> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring"/> + </xsl:when> + <xsl:when test="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"> + <xsl:apply-templates select="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"/> <!-- TODO: emphasize -->(generic description) + </xsl:when> + <xsl:otherwise> + (Undocumented.) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="signal" mode="detail"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: signal </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a signal of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="not(@direction)"/> + <xsl:when test="@direction='in'"> + <xsl:message terminate="no"> + <xsl:text>INFO: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has unnecessary direction 'in'</xsl:text> + </xsl:message> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction other than 'in'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + + <refsection> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@name, concat('.', @name))"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="concat(../@name, concat('.', @name))"/></literal> + </title> + <xsl:apply-templates select="." mode="funcsynopsis"/> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + + <xsl:if test="arg"> + <glosslist> + <xsl:apply-templates select="arg" mode="paramtable"/> + </glosslist> + </xsl:if> + </refsection> + </xsl:template> + + <xsl:template match="/tp:spec"> + <book xmlns="http://docbook.org/ns/docbook" version="5.0"> + <bookinfo> + <title><xsl:value-of select="tp:title"/></title> + <xsl:apply-templates select="tp:copyright"/> + <xsl:apply-templates select="tp:license"/> + <xsl:if test="tp:docstring"> + <abstract> + <xsl:apply-templates select="tp:docstring"/> + </abstract> + </xsl:if> + <!-- TODO: Version + <xsl:if test="tp:version"> + <xsl:text> version </xsl:text> + <xsl:value-of select="tp:version"/> + </xsl:if> --> + </bookinfo> + <chapter> + <xsl:attribute name="xml:id">interfaces</xsl:attribute> + <title>Interfaces</title> + <xsl:apply-templates select="//node"/> + </chapter> + <xsl:call-template name="generic-types"/> + <xsl:if test="tp:errors"> + <chapter> + <xsl:attribute name="xml:id">errors</xsl:attribute> + <xsl:apply-templates select="tp:errors"/> + </chapter> + </xsl:if> + </book> + </xsl:template> + + <xsl:template match="node"> + <xsl:apply-templates /> + </xsl:template> + + <xsl:template match="text()"> + <xsl:if test="normalize-space(.) != ''"> + <xsl:message terminate="yes"> + <xsl:text>Stray text: {{{</xsl:text> + <xsl:value-of select="." /> + <xsl:text>}}} </xsl:text> + </xsl:message> + </xsl:if> + </xsl:template> + + <xsl:template match="*"> + <xsl:message terminate="yes"> + <xsl:text>Unrecognised element: {</xsl:text> + <xsl:value-of select="namespace-uri(.)" /> + <xsl:text>}</xsl:text> + <xsl:value-of select="local-name(.)" /> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:template> +</xsl:stylesheet> + +<!-- vim:set sw=2 sts=2 et: --> diff --git a/secret-service/tools/spec-to-introspect.xsl b/secret-service/tools/spec-to-introspect.xsl new file mode 100644 index 0000000..ca8b4b6 --- /dev/null +++ b/secret-service/tools/spec-to-introspect.xsl @@ -0,0 +1,147 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + exclude-result-prefixes="tp"> + +<!-- + Telepathy D-Bus Introspection to EggDBus Introspection format translator. + + Copyright 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +--> + +<!-- + TODO: + - Enable conversion of dictionary element types (eg. "{ss}") and + struct types (eg. "(sayay)") + - unhandled: tp:simple-type, tp:enum, tp:flags, tp:external-type + - tp:docstring may contain XHTML which this template doesn't handle +--> + + <xsl:include href="resolve-type.xsl"/> + + <!-- main template --> + <xsl:template match="tp:spec"> + <node> + <xsl:apply-templates select="tp:errors"/> + <xsl:apply-templates select="tp:struct"/> + <!-- TODO: <xsl:apply-templates select="tp:mapping"/> --> + <xsl:apply-templates select="node/interface"/> + </node> + </xsl:template> + + <!-- handle most of the D-Bus introspection elements --> + <xsl:template match="interface|annotation|method|signal"> + <xsl:copy> + <xsl:for-each select="@*"> + <xsl:if test="not(starts-with(name(), 'tp:'))"> + <xsl:copy/> + </xsl:if> + </xsl:for-each> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- handle the arg and property D-Bus introspection elements. + They get special handling because they may contain a tp:type + attribute --> + <xsl:template match="arg|property"> + <xsl:copy> + <xsl:for-each select="@*"> + <xsl:choose> + <xsl:when test="not(starts-with(name(), 'tp:'))"> + <xsl:copy/> + </xsl:when> + <xsl:when test="name() = 'tp:type'"> + <xsl:variable name="type"> + <xsl:call-template name="TpType"> + <xsl:with-param name="type" select="."/> + </xsl:call-template> + </xsl:variable> + <annotation name="org.gtk.EggDBus.Type"> + <xsl:attribute name="value"> + <xsl:value-of select="translate(translate($type, ' ', ''), '
', '')"/> + </xsl:attribute> + </annotation> + </xsl:when> + <xsl:otherwise/> + </xsl:choose> + </xsl:for-each> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- tp:docstring to org.gtk.EggDBus.DocString --> + <xsl:template match="tp:docstring"> + <annotation name="org.gtk.EggDBus.DocString"> + <xsl:attribute name="value"> + <xsl:value-of select="normalize-space(text())"/> + </xsl:attribute> + </annotation> + </xsl:template> + + <!-- tp:errors to org.gtk.EggDBus.DeclareErrorDomain --> + <xsl:template match="tp:errors"> + <annotation value="Error" name="org.gtk.EggDBus.DeclareErrorDomain"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:error"/> + </annotation> + </xsl:template> + + <!-- tp:error to org.gtk.EggDBus.ErrorDomain.Member --> + <xsl:template match="tp:error"> + <annotation name="org.gtk.EggDBus.ErrorDomain.Member"> + <xsl:attribute name="value"> + <xsl:value-of select="concat(../@namespace, '.', @name)"/> + </xsl:attribute> + <xsl:apply-templates select="tp:docstring"/> + </annotation> + </xsl:template> + + <!-- tp:struct to org.gtk.EggDBus.DeclareStruct --> + <xsl:template match="tp:struct"> + <annotation name="org.gtk.EggDBus.DeclareStruct"> + <xsl:attribute name="value"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:member"/> + </annotation> + </xsl:template> + + <!-- tp:member to org.gtk.EggDBus.Struct.Member --> + <xsl:template match="tp:member"> + <xsl:variable name="type"> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:variable> + <annotation name="org.gtk.EggDBus.Struct.Member"> + <xsl:attribute name="value"> + <xsl:value-of select="concat(normalize-space($type), ':', @name)"/> + </xsl:attribute> + <xsl:apply-templates select="tp:docstring"/> + </annotation> + </xsl:template> + + <xsl:template match="text()"/> + + <xsl:output method="xml" indent="yes" encoding="UTF-8" + omit-xml-declaration="no" + doctype-system="http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" + doctype-public="-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"/> + +</xsl:stylesheet> |