<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 17405 -->
<!-- Reviewed: no -->
<sect1 id="zend.http.cookies">
    <title>Zend_Http_Cookie und Zend_Http_CookieJar</title>

    <sect2 id="zend.http.cookies.introduction">
        <title>Einführung</title>
        <para>
            Wie erwartet ist <classname>Zend_Http_Cookie</classname> eine Klasse, die einen
            <acronym>HTTP</acronym> Cookie darstellt. Sie stellt Methoden zum Verarbeiten von
            <acronym>HTTP</acronym> Antwort-Strings, Sammeln von Cookies und dem einfachen Zugriff
            auf deren Eigenschaften zur Verfügung. So ist es auch möglich verschiedene Zustände
            eines Cookies zu überprüfen, z.B. den Anfrage <acronym>URL</acronym>, die Ablaufzeit,
            das Vorliegen einer sicheren Verbindung, etc.
        </para>
        <para>
            <classname>Zend_Http_CookieJar</classname> ist ein Objekt, das normalerweise von der
            Klasse <classname>Zend_Http_Client</classname> genutzt wird und einen Satz von
            <classname>Zend_Http_Cookie</classname> Objekten beinhaltet. Die Idee ist das wenn ein
            <classname>Zend_Http_CookieJar</classname> an ein
            <classname>Zend_Http_Client</classname> Objekt angehängt wird, alle ein- und ausgehenden
            Cookies der <acronym>HTTP</acronym> Anfragen und -Antworten im CookieJar Objekt
            gespeichert werden. Bei einer neuen Anfrage seitens des Clients wird nach allen Cookies,
            die auf diese Anfrage zutreffen, gesucht. Diese werden automatisch
            zum Anfrage-Header hinzugefügt, was besonders nützlich ist, wenn man
            eine Benutzersession über aufeinanderfolgende <acronym>HTTP</acronym> Anfragen
            beibehalten muss; die Session-ID wird automatisch gesendet, wenn es notwendig ist.
            Ferner ist es möglich, <classname>Zend_Http_CookieJar</classname> Objekte zu
            serialisieren und, wenn nötig, in $_SESSION zu speichern.
        </para>
    </sect2>

    <sect2 id="zend.http.cookies.cookie.instantiating">
        <title>Instanzieren von Zend_Http_Cookie Objekten</title>
        <para>
            Es gibt zwei Möglichkeiten ein Cookie Objekt zu erstellen:
            <itemizedlist>
                <listitem>
                    <para>
                    Mithilfe des Konstruktors und der folgenden Syntax:
                    <code>new <classname>Zend_Http_Cookie</classname>(string $name, string $value, string $domain, [int
                       $expires, [string $path, [boolean $secure]]]);</code>
                    </para>
                    <itemizedlist>
                        <listitem>
                            <para>
                                <varname>$name</varname>: Name des Cookies (notwendig)
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <varname>$value</varname>: Inhalt des Cookies (notwendig)
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <varname>$domain</varname>: Die Domain des Cookies (z.B.
                                '.example.com') (notwendig)
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <varname>$expires</varname>: Ablaufzeit des Cookies als UNIX
                                Zeitstempel (optional, standardmäßig null). Ein Nichtsetzen führt zu
                                einer Behandlung als 'Session-Cookie', das keine Ablaufzeit enthält.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <varname>$path</varname>: Pfad des Cookies, z.B. '/foo/bar/'
                                (optional, standardmäßig '/')
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <varname>$secure</varname>: Boolean, ob der Cookie nur über sichere
                                Verbindungen (HTTPS) gesendet werden darf (optional, standardmäßig
                                boolean FALSE)
                            </para>
                        </listitem>
                    </itemizedlist>
                </listitem>
                <listitem>
                    <para>
                        Durch das Aufrufen der statischen fromString()-Methode mit einem
                        Cookie-String, wie er unter 'Set-Cookie' in einer <acronym>HTTP</acronym>
                        Antwort und 'Cookie' in einer <acronym>HTTP</acronym> Anfrage zu finden ist.
                        In diesem Fall muss der Cookie-Inhalt bereits kodiert sein. Falls der
                        Cookie-String keinen 'domain'-Teil enthält, muss man selbst einen Referenz
                        <acronym>URI</acronym> angeben, aus dem die Domain und der Pfad des Cookies
                        bestimmt wird.
                    </para>
                </listitem>
            </itemizedlist>
            <example id="zend.http.cookies.cookie.instantiating.example-1">
               <title>Instanzieren eines Zend_Http_Cookie-Objekts</title>
               <programlisting language="php"><![CDATA[
// Zuerst nutzen wir den Konstruktor. Der Cookie wird in zwei Stunden ablaufen
$cookie = new Zend_Http_Cookie('foo',
                               'bar',
                               '.example.com',
                               time() + 7200,
                               '/path');

// Man kann auch den HTTP-Antwort 'Set-Cookie'-header dafür nutzen.
// Dieser Cookie ist ähnlich zum vorangegangenen, allerdings wird
// er nicht ablaufen und nur über sichere Verbindungen gesendet.
$cookie = Zend_Http_Cookie::fromString('foo=bar; domain=.example.com; ' .
                                       'path=/path; secure');

// Wenn die Domain des Cookies nicht gesetzt ist, muss man ihn selbst angeben.
$cookie = Zend_Http_Cookie::fromString('foo=bar; secure;',
                                       'http://www.example.com/path');
]]></programlisting>
            </example>
            <note>
                <para>
                    Beim Instanzieren eines Cookie Objekts mit der
                    <classname>Zend_Http_Cookie</classname>::fromString()-Methode wird erwartet,
                    dass der Cookie-Inhalt <acronym>URL</acronym> kodiert ist, wie es bei
                    Cookie-Strings sein sollte. Allerdings wird angenommen, dass der Inhalt bei
                    Verwendung des Konstruktors in seiner eigentlichen Form, d.h. nicht URL-kodiert,
                    übergeben wird.
                </para>
            </note>
        </para>
        <para>
            Ein Cookie Objekt kann durch die magische __toString()-Methode zurück in einen String
            umgewandelt werden. Diese Methode erstellt einen HTTP-Anfrage "Cookie"-Header String,
            der den Namen sowie den Inhalt des Cookies enthält und durch ein Semikolon (';')
            abgeschlossen ist. Der Inhalt wird URL-kodiert, wie es für einen Cookie-Header
            vorgeschrieben ist:
            <example id="zend.http.cookies.cookie.instantiating.example-2">
               <title>Transformation eines Zend_Http_Cookie-Objekts zu einem String</title>
               <programlisting language="php"><![CDATA[
// Erstellt einen neuen Cookie
$cookie = new Zend_Http_Cookie('foo',
                               'two words',
                               '.example.com',
                               time() + 7200,
                               '/path');

// Gibt 'foo=two+words;' aus
echo $cookie->__toString();

// Bezweckt dasselbe
echo (string) $cookie;

// Ab PHP 5.2 funktioniert auch diese Variante
echo $cookie;
]]></programlisting>
            </example>
        </para>
    </sect2>

    <sect2 id="zend.http.cookies.cookie.accessors">
        <title>Zend_Http_Cookie getter-Methoden</title>
        <para>
            Sobald ein <classname>Zend_Http_Cookie</classname> instanziert wurde, stellt es diverse
            getter-Methoden zur Verfügung, die es einem ermöglichen, auf die verschiedenen
            Eigenschaften des <acronym>HTTP</acronym> Cookies zuzugreifen:
            <itemizedlist>
                <listitem>
                    <para>
                        <code>string getName()</code>: Gibt den Namen des Cookies zurück
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>string getValue()</code>: Gibt den wirklichen, also nicht kodierten,
                        Inhalt zurück
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>string getDomain()</code>: Gibt die Domain des Cookies zurück
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>string getPath()</code>: Gibt den Pfad des Cookies zurück; dessen
                        Standardwert ist '/'
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>int getExpiryTime()</code>: Gibt die Ablaufzeit des Cookies als
                        UNIX-Timestamp zurück. Falls der Cookie keine Ablaufzeit besitzt, wird NULL
                        zurückgegeben.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
        <para>
            Zusätzlich gibt es einige boolesche tester-Methoden:
            <itemizedlist>
                <listitem>
                    <para>
                        <code>boolean isSecure()</code>: Gibt zurück, ob der Cookie nur über sichere
                        Verbindungen gesendet werden kann. Wenn true zurückgegeben wird, wird der
                        Cookie also nur über <acronym>HTTPS</acronym> versendet.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>boolean isExpired(int $time = null)</code>: Überprüft, ob der Cookie
                        bereits abgelaufen ist. Wenn der Cookie keine Ablaufzeit besitzt, wird diese
                        Methode immer true zurückgegeben. Wenn $time übergeben wurde, wird der
                        aktuelle Zeitstempel überschrieben und der übergebene Zeitstempel zur
                        Überprüfung genutzt.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>boolean isSessionCookie()</code>: Überprüft, ob der Cookie ein
                        "Session-Cookie" ist, der keine Ablaufzeit besitzt und erst abläuft, wenn
                        die Session beendet wird.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
        <para>
            <example id="zend.http.cookies.cookie.accessors.example-1">
                <title>Nutzen der getter-Methoden von Zend_Http_Cookie</title>
                <programlisting language="php"><![CDATA[
// Zuerst wird der Cookie erstellt
$cookie = Zend_Http_Cookie::fromString(
    'foo=two+words; ' +
    'domain=.example.com; ' +
    'path=/somedir; ' +
    'secure; ' +
    'expires=Wednesday, 28-Feb-05 20:41:22 UTC');

echo $cookie->getName();   // Gibt 'foo' aus
echo $cookie->getValue();  // Gibt 'two words' aus
echo $cookie->getDomain(); // Gibt '.example.com' aus
echo $cookie->getPath();   // Gibt '/' aus

echo date('Y-m-d', $cookie->getExpiryTime());
// Gibt '2005-02-28' aus

echo ($cookie->isExpired() ? 'Ja' : 'Nein');
// Gibt 'Ja' aus

echo ($cookie->isExpired(strtotime('2005-01-01') ? 'Ja' : 'Nein');
// Gibt 'Nein' aus

echo ($cookie->isSessionCookie() ? 'Ja' : 'Nein');
// Gibt 'Nein' aus
]]></programlisting>
            </example>
        </para>
    </sect2>

    <sect2 id="zend.http.cookies.cookie.matching">
        <title>Zend_Http_Cookie: Überprüfen von Szenarien</title>
        <para>
            Die einzige wirkliche Logik in einem <classname>Zend_Http_Cookie</classname> Objekt
            befindet sich in der match()-Methode. Sie wird genutzt um zu Überprüfen, ob ein Cookie
            auf eine <acronym>HTTP</acronym> Anfrage zutrifft, um zu entscheiden, ob der Cookie in
            der Anfrage gesendet werden soll. Die Methode hat folgende Syntax und Parameter:
            <code>boolean Zend_Http_Cookie->match(mixed $uri, [boolean $matchSessionCookies,
                [int $now]]);</code>
            <itemizedlist>
                <listitem>
                    <para>
                        <code>mixed $uri</code>: Ein zu überprüfendes
                        <classname>Zend_Uri_Http</classname> Objekt mit einer Domain und einem Pfad.
                        Wahlweise kann stattdessen jedoch auch ein String, der einen validen
                        <acronym>HTTP</acronym> <acronym>URL</acronym> darstellt, übergeben werden.
                        Der Cookie ist zutreffend, wenn das <acronym>URL</acronym> Schema (HTTP oder
                        <acronym>HTTPS</acronym>), die Domain sowie der Pfad passen.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>boolean $matchSessionCookies</code>: Gibt an, ob Session-Cookies
                        zutreffen sollen. Standardmäßig ist dieser Parameter true. Wenn false
                        stattdessen übergeben wird, werden Cookies ohne Ablaufzeit nie zutreffen.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>int $now</code>: Ablaufzeit (in Form eines UNIX-Zeitstempels) auf
                        welche der Cookie überprüft wird. Wenn sie nicht angegeben wird, wird die
                        gegenwärtige Zeit genutzt.
                    </para>
                </listitem>
            </itemizedlist>
            <example id="zend.http.cookies.cookie.matching.example-1">
                <title>Zutreffen von Cookies</title>
                <programlisting language="php"><![CDATA[
// Erstellen eines Cookie Objekts - zuerst ein sicherer Cookie ohne Ablaufzeit
$cookie = Zend_Http_Cookie::fromString('foo=two+words; ' +
                                       'domain=.example.com; ' +
                                       'path=/somedir; ' +
                                       'secure;');

$cookie->match('https://www.example.com/somedir/foo.php');
// Gibt true zurück

$cookie->match('http://www.example.com/somedir/foo.php');
// Gibt false zurück, da die Verbindung nicht sicher ist

$cookie->match('https://otherexample.com/somedir/foo.php');
// Gibt false zurück, da die Domain falsch ist

$cookie->match('https://example.com/foo.php');
// Gibt false zurück, da der Pfad falsch ist

$cookie->match('https://www.example.com/somedir/foo.php', false);
// Gibt false zurück, da keine Session-Cookies akzeptiert werden

$cookie->match('https://sub.domain.example.com/somedir/otherdir/foo.php');
// Gibt true zurück

// Erstellen eines anderen Cookie-Objekts - diesmal unsicher und
// einer Ablaufzeit die zwei Stunden in der Zukunft liegt
$cookie = Zend_Http_Cookie::fromString('foo=two+words; ' +
                                       'domain=www.example.com; ' +
                                       'expires='
                                       . date(DATE_COOKIE, time() + 7200));

$cookie->match('http://www.example.com/');
// Gibt true zurück

$cookie->match('https://www.example.com/');
// Gibt true zurück, da unsichere Cookies genauso gut über sichere
// Verbindungen übertragen werden können

$cookie->match('http://subdomain.example.com/');
// Gibt false zurück, da die Domain unzutreffend ist

$cookie->match('http://www.example.com/', true, time() + (3 * 3600));
// Gibt false zurück, da die Ablaufzeit drei Stunden in der Zukunft
// liegt
]]></programlisting>
            </example>
        </para>
    </sect2>

    <sect2 id="zend.http.cookies.cookiejar">
        <title>Die Zend_Http_CookieJar Klasse: Instanzierung</title>
        <para>
            In den meisten Fällen ist es nicht notwendig, ein
            <classname>Zend_Http_CookieJar</classname> Objekt direkt zu erstellen. Wenn man ein
            neues CookieJar zum <classname>Zend_Http_Client</classname> Objekts hinzufügen will,
            muss man lediglich die Methode Zend_Http_Client->setCookieJar( aufrufen, die ein neues
            und leeres CookieJar zum Client hinzufügt. Später kann man dieses CookieJar via
            Zend_Http_Client->getCookieJar() holen.
        </para>
        <para>
            Wenn dennoch ein CookieJar Objekt manuell erstellen werden soll, kann man dies
            direkt durch "new Zend_Http_CookieJar()" erreichen - der Konstruktor benötigt
            keine Parameter. Ein anderer Weg zum Instanzieren eines CookieJar Objekts ist
            es, die statische Methode Zend_Http_CookieJar::fromResponse() zu nutzen. Diese
            Methode benötigt zwei Parameter: ein <classname>Zend_Http_Response</classname> Objekt
            und einen Referenz <acronym>URI</acronym>, entweder in Form eines Strings oder eines
            <classname>Zend_Uri_Http</classname> Objekts. Es wird ein
            <classname>Zend_Http_CookieJar</classname> Objekt zurückgegeben, das bereits die
            Cookies, die durch die <acronym>HTTP</acronym> Antwort gesetzt wurden, enthält. Der
            Referenz <acronym>URI</acronym> wird genutzt um die Domain und den Pfad des Cookies zu
            setzen, sofern sie nicht in den Set-Cookie-Headern definiert wurden.
        </para>
    </sect2>

    <sect2 id="zend.http.cookies.cookiejar.adding_cookies">
        <title>Hinzufügen von Cookies zu einem Zend_Http_CookieJar Objekt</title>
        <para>
            Normalerweise werden die, durch <acronym>HTTP</acronym> Antworten gesetzen, Cookies vom
            <classname>Zend_Http_Client</classname> Objekt automatisch zu dessen CookieJar
            hinzugefügt. Wenn man es wünscht, kann man Cookies auch manuell zum CookieJar
            hinzufügen, was durch Nutzen zweier Methoden erreicht werden kann:
            <itemizedlist>
                <listitem>
                    <para>
                        <classname>Zend_Http_CookieJar->addCookie($cookie[, $ref_uri])</classname>:
                        Hinzufügen eines einzelnen Cookies zum CookieJar. $cookie kann entweder ein
                        <classname>Zend_Http_Cookie</classname> Objekt oder ein String, der
                        automatisch zu einem Cookie Objekt transformiert wird, sein. Wenn ein String
                        übergeben wird, sollte man jedoch zusätzlich immer $ref_uri übergeben, da
                        dieser einen Referenz <acronym>URI</acronym> darstellt - in Form eines
                        Strings oder eines <classname>Zend_Uri_Http</classname> Objekts - dessen
                        Werte als Standard für die Domain und den Pfad des Cookies genutzt werden.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <classname>Zend_Http_CookieJar->addCookiesFromResponse($response,
                            $ref_uri)</classname>: Fügt alle Cookies zum CookieJar hinzu, die in
                        einer einzelnen <acronym>HTTP</acronym> Antwort gesetzt wurden. Es wird
                        erwartet, dass $response ein <classname>Zend_Http_Response</classname>
                        Objekt mit Set-Cookie-Headern ist. $ref_uri ist ein Anfrage
                        <acronym>URI</acronym> in Form eines Strings oder eines
                        <classname>Zend_Uri_Http</classname> Objekts dessen Inhalt die
                        Standarddomain und den -pfad des Cookies bestimmt.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
    </sect2>

    <sect2 id="zend.http.cookies.cookiejar.getting_cookies">
        <title>Abrufen der Cookies von einem Zend_Http_CookieJar-Objekts</title>
        <para>
            Wie beim Hinzufügen von Cookies ist es normalerweise nicht notwendig,
            die Cookies manuell von einem CookieJar Objekt zu holen. Das
            <classname>Zend_Http_Client</classname> Objekt holt automatisch alle benötigten Cookies
            für eine <acronym>HTTP</acronym> Anfrage. Allerdings gibt es drei Methoden die Cookies
            aus einem CookieJar zu holen: <methodname>getCookie()</methodname>,
            <methodname>getAllCookies()</methodname>, und
            <methodname>getMatchingCookies()</methodname>. Zusätzlich erhält man alle
            <classname>Zend_Http_Cookie</classname> Objekte von CookieJar wenn man durch Ihn
            iteriert.
        </para>
        <para>
            Es ist wichtig anzumerken, dass jede dieser Methoden einen speziellen
            Parameter verlangt, der den Rückgabetyp der Methode festlegt. Dieser
            Parameter kann drei verschiedene Werte annehmen:
            <itemizedlist>
                <listitem>
                    <para>
                    <constant>Zend_Http_CookieJar::COOKIE_OBJECT</constant>: Gibt ein
                    <classname>Zend_Http_Cookie</classname> Objekt zurück. Wenn diese Methode mehr
                    als einen Cookie zurückgeben sollte, wird stattdessen ein Array aus Objekten
                    zurückgegeben.
                    </para>
                </listitem>
                <listitem>
                    <para>
                    <constant>Zend_Http_CookieJar::COOKIE_STRING_ARRAY</constant>: Gibt Cookies
                    als Strings - im Format "foo=bar" - zurück, welche passend für das
                    Senden im "Cookie"-Header einer <acronym>HTTP</acronym>Anfrage sind. Wenn mehr
                    als ein Cookie zurückgegeben werden sollte, wird stattdessen ein Array
                    solcher Strings zurückgegeben.
                    </para>
                </listitem>
                <listitem>
                    <para>
                    <constant>Zend_Http_CookieJar::COOKIE_STRING_CONCAT</constant>: Ähnlich zu
                    COOKIE_STRING_ARRAY; allerdings gibt diese Methode, falls mehr als
                    ein Cookie zurückgegeben wird, einen einzelnen, langen String zurück,
                    der die Cookies anhand eines Semikolons (;) trennt. Dieses Prozedere
                    ist besonders hilfreich, wenn man alle zutreffenden Cookies in einem
                    einzelnen "Cookie"-Header einer <acronym>HTTP</acronym> Anfrage zurückgeben
                    will.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
        <para>
            Die Struktur der unterschiedlichen Cookie-Abrufmethoden wird unterhalb beschrieben:
            <itemizedlist>
                <listitem>
                    <para>
                    <classname>Zend_Http_CookieJar->getCookie($uri, $cookie_name[,
                        $ret_as])</classname>: Gibt einen einzelnen Cookie von dem CookieJar zurück,
                    dessen <acronym>URI</acronym> (Domain und Pfad) und Name zu den Parametern
                    passen. $uri ist entweder ein String oder ein
                    <classname>Zend_Http_Uri</classname> Objekt, die den <acronym>URI</acronym>
                    darstellen. $cookie_name ist ein String zum Identifizieren des Cookie-Namens.
                    $ret_as ist ein optionaler Parameter, der angibt, von welchem Typ der
                    zurückgegebene Wert ist. Der Standardwert ist COOKIE_OBJECT.
                    </para>
                </listitem>
                <listitem>
                    <para>
                    <classname>Zend_Http_CookieJar->getAllCookies($ret_as)</classname>: Holt alle
                    Cookies aus dem CookieJar. $ret_as gibt den Rückgabetyp - wie oben bereits
                    beschrieben - an. Wenn er nicht angegeben wird, nimmt er COOKIE_OBJECT an.
                    </para>
                </listitem>
                <listitem>
                    <para>
                    <classname>Zend_Http_CookieJar->getMatchingCookies($uri[, $matchSessionCookies[,
                        $ret_as[, $now]]])</classname>: Gibt alle Cookies vom CookieJar zurück, die
                    mit der Ablaufzeit und dem <acronym>URI</acronym> übereinstimmen.
                    <itemizedlist>
                        <listitem>
                            <para>
                            <varname>$uri</varname> ist entweder ein
                            <classname>Zend_Uri_Http</classname> Objekt oder ein String, der den
                            Verbindungstyp (sicher oder unsicher), die Domain und den Pfad angibt.
                            Nach diesen Informationen wird im CookieJar gesucht.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                            <varname>$matchSessionCookies</varname> ist ein boolescher Ausdruck, der
                            festlegt, ob nach Session-Cookies gesucht werden soll. Session-Cookies
                            sind Cookies, die keine Ablaufzeit enthalten. Standardmäßig ist dieser
                            Wert true.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                            <varname>$ret_as</varname> gibt den Rückgabetyp - wie oben beschrieben
                            - an. Wenn keiner angegeben wird, wird COOKIE_OBJECT angenommen.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                            <varname>$now</varname> ist ein Integer der einen UNIX-Zeitstempel
                            darstellt. Cookies, die vor der angegeben Zeit ablaufen, werden nicht
                            zurückgegeben. Wenn dieser Parameter nicht angegeben wird, wird
                            stattdessen die aktuelle Zeit gewählt.
                            </para>
                        </listitem>
                    </itemizedlist>
                    Mehr über das Zutreffen von Cookies gibt es hier:
                    <xref linkend="zend.http.cookies.cookie.matching" />.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
