summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2010-12-04 16:12:09 +0000
committerStef Walter <stefw@collabora.co.uk>2010-12-04 16:12:09 +0000
commitcc3bb7a99ed787afee61159143270a63ab32efd8 (patch)
tree911a9b40e55695e8a9995e5fdbb3df89c94ccef2
parent5c950648d4e3b186bda82c0c27ef089ee6747cbd (diff)
parentacb853368b95d07c01e2ac48af258d141ea4f0ce (diff)
downloadxdg-specs-cc3bb7a99ed787afee61159143270a63ab32efd8.tar.xz
Merge branch 'secret-service'
-rw-r--r--secret-service/.gitignore3
-rw-r--r--secret-service/Makefile10
-rw-r--r--secret-service/README20
-rw-r--r--secret-service/docbook-params.xsl39
-rw-r--r--secret-service/html/style.css127
-rw-r--r--secret-service/org.freedesktop.Secrets.xml427
-rw-r--r--secret-service/specification.xml505
-rw-r--r--secret-service/tools/resolve-type.xsl122
-rw-r--r--secret-service/tools/spec-to-docbook.xsl1239
-rw-r--r--secret-service/tools/spec-to-introspect.xsl147
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 &lt;stef@memberwebs.com&gt;
+ </tp:copyright>
+ <tp:copyright>
+ Copyright (C) 2009 Michael Leupold &lt;lemma@confuego.org&gt;
+ </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, ' ', ''), '&#xa;', '')"/>
+ </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&lt;
+ <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>
+ &gt;
+ </xsl:when>
+ <xsl:when test="starts-with($type, 'a')">
+ Array&lt;
+ <xsl:call-template name="DBusType">
+ <xsl:with-param name="type" select="substring($type, 2)"/>
+ </xsl:call-template>
+ &gt;
+ </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&lt;
+ <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>
+ &gt;
+ </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>'&#10;</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> &lt;interface&gt;&#10;</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>&#10;</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&#10;</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>&#10;</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&#10;</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>&#10;</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>'&#10;</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>'&#10;</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&#10;</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>&#10;</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>'&#10;</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&#10;</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>&#10;</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&#10;</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>&#10;</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()"> &#x2192; </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&#10;</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>&#10;</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>'&#10;</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>'&#10;</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&#10;</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>&#10;</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>}}}&#10;</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>&#10;</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, ' ', ''), '&#xa;', '')"/>
+ </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>