]> source.dussan.org Git - nextcloud-server.git/commitdiff
Test ownCloud CardDAV sharing using CalDAVTester
authorThomas Müller <thomas.mueller@tmit.eu>
Tue, 12 Jan 2016 12:23:50 +0000 (13:23 +0100)
committerThomas Müller <thomas.mueller@tmit.eu>
Mon, 18 Jan 2016 21:14:51 +0000 (22:14 +0100)
23 files changed:
apps/dav/lib/carddav/addressbook.php
apps/dav/lib/carddav/card.php
apps/dav/lib/carddav/carddavbackend.php
apps/dav/lib/carddav/sharing/plugin.php
apps/dav/lib/carddav/sharing/xml/sharerequest.php
apps/dav/tests/travis/caldavtest/config/serverinfo.dtd [deleted file]
apps/dav/tests/travis/caldavtest/config/serverinfo.xml [deleted file]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/1.xml [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/4.xml [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/6.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/7.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/8.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/9.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vcurrent-user-principal/1.xml [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/1.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/2.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/3.vcf [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/sync/1.xml [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/sync/2.xml [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/serverinfo.dtd [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/serverinfo.xml [new file with mode: 0644]
apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml [new file with mode: 0644]
apps/dav/tests/travis/carddav/script.sh

index 3e3e751828e8a2b4ab3d9067efe43d011a1adcdf..34b580827c17c7e946d12daa2543885a488cfacb 100644 (file)
@@ -68,7 +68,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddres
        function getShares() {
                /** @var CardDavBackend $carddavBackend */
                $carddavBackend = $this->carddavBackend;
-               $carddavBackend->getShares($this->getName());
+               return $carddavBackend->getShares($this->getBookId());
        }
 
        function getACL() {
@@ -81,7 +81,26 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddres
                        ];
                }
 
-               return $acl;
+               // add the current user
+               if (isset($this->addressBookInfo['{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal'])) {
+                       $owner = $this->addressBookInfo['{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal'];
+                       $acl[] = [
+                                       'privilege' => '{DAV:}read',
+                                       'principal' => $owner,
+                                       'protected' => true,
+                               ];
+                       if ($this->addressBookInfo['{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only']) {
+                               $acl[] = [
+                                       'privilege' => '{DAV:}write',
+                                       'principal' => $owner,
+                                       'protected' => true,
+                               ];
+                       }
+               }
+
+               /** @var CardDavBackend $carddavBackend */
+               $carddavBackend = $this->carddavBackend;
+               return $carddavBackend->applyShareAcl($this->getBookId(), $acl);
        }
 
        function getChildACL() {
@@ -94,7 +113,9 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddres
                        ];
                }
 
-               return $acl;
+               /** @var CardDavBackend $carddavBackend */
+               $carddavBackend = $this->carddavBackend;
+               return $carddavBackend->applyShareAcl($this->getBookId(), $acl);
        }
 
        function getChild($name) {
@@ -105,4 +126,8 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddres
                return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
        }
 
+       private function getBookId() {
+               return $this->addressBookInfo['id'];
+       }
+
 }
index 5ec9a7e93a9e0bc5318d45f044fb392e41261eb5..d848f2e28ecd5faf04ea14400d389107eb03cdb8 100644 (file)
@@ -33,7 +33,13 @@ class Card extends \Sabre\CardDAV\Card {
                        ];
                }
 
-               return $acl;
+               /** @var CardDavBackend $carddavBackend */
+               $carddavBackend = $this->carddavBackend;
+               return $carddavBackend->applyShareAcl($this->getBookId(), $acl);
+       }
+
+       private function getBookId() {
+               return $this->addressBookInfo['id'];
        }
 
 }
index e8a5a77664611f4e57eac950e44e96fad45b3704..3a98fd6e8104887542dbe3179d56bf350f7e3725 100644 (file)
@@ -53,6 +53,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
                        'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME',
                        'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO', 'CLOUD');
 
+       const ACCESS_OWNER = 1;
+       const ACCESS_READ_WRITE = 2;
+       const ACCESS_READ = 3;
+
        /**
         * CardDavBackend constructor.
         *
@@ -109,14 +113,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
                $principals[]= $principalUri;
 
                $query = $this->db->getQueryBuilder();
-               $query2 = $this->db->getQueryBuilder();
-               $query2->select(['resourceid'])
-                       ->from('dav_shares')
-                       ->where($query2->expr()->in('principaluri', $query2->createParameter('principaluri')))
-                       ->andWhere($query2->expr()->eq('type', $query2->createParameter('type')));
-               $result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])
-                       ->from('addressbooks')
-                       ->where($query->expr()->in('id', $query->createFunction($query2->getSQL())))
+               $result = $query->select(['a.id', 'a.uri', 'a.displayname', 'a.principaluri', 'a.description', 'a.synctoken', 's.uri', 's.access'])
+                       ->from('dav_shares', 's')
+                       ->join('s', 'addressbooks', 'a', 's.resourceid = a.id')
+                       ->where($query->expr()->in('s.principaluri', $query->createParameter('principaluri')))
+                       ->andWhere($query->expr()->eq('s.type', $query->createParameter('type')))
                        ->setParameter('type', 'addressbook')
                        ->setParameter('principaluri', $principals, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
                        ->execute();
@@ -125,11 +126,13 @@ class CardDavBackend implements BackendInterface, SyncSupport {
                        $addressBooks[] = [
                                'id'  => $row['id'],
                                'uri' => $row['uri'],
-                               'principaluri' => $row['principaluri'],
+                               'principaluri' => $principalUri,
                                '{DAV:}displayname' => $row['displayname'],
                                '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
                                '{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
                                '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
+                               '{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'],
+                               '{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => $row['access'] === self::ACCESS_READ,
                        ];
                }
                $result->closeCursor();
@@ -782,12 +785,14 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 
                // remove the share if it already exists
                $this->unshare($addressBookUri, $element['href']);
+               $access = $element['readOnly'] ? self::ACCESS_READ : self::ACCESS_READ_WRITE;
 
+               $newUri = sha1($addressBookUri . $addressBook['principaluri']);
                $query = $this->db->getQueryBuilder();
                $query->insert('dav_shares')
                        ->values([
                                'principaluri' => $query->createNamedParameter($parts[1]),
-                               'uri' => $query->createNamedParameter($addressBookUri),
+                               'uri' => $query->createNamedParameter($newUri),
                                'type' => $query->createNamedParameter('addressbook'),
                                'access' => $query->createNamedParameter(0),
                                'resourceid' => $query->createNamedParameter($addressBook['id'])
@@ -835,11 +840,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
         *
         * @return array
         */
-       public function getShares($addressBookUri) {
+       public function getShares($addressBookId) {
                $query = $this->db->getQueryBuilder();
                $result = $query->select(['principaluri', 'access'])
                        ->from('dav_shares')
-                       ->where($query->expr()->eq('uri', $query->createNamedParameter($addressBookUri)))
+                       ->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBookId)))
                        ->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook')))
                        ->execute();
 
@@ -850,7 +855,8 @@ class CardDavBackend implements BackendInterface, SyncSupport {
                                'href' => "principal:${p['uri']}",
                                'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
                                'status' => 1,
-                               'readOnly' => ($row['access'] === 1)
+                               'readOnly' => ($row['access'] === self::ACCESS_READ),
+                               '{'.\OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD.'}principal' => $p['uri']
                        ];
                }
 
@@ -945,4 +951,29 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 
                return (int)$cardIds['id'];
        }
+
+       /**
+        * @param $addressBookId
+        * @param $acl
+        * @return array
+        */
+       public function applyShareAcl($addressBookId, $acl) {
+
+               $shares = $this->getShares($addressBookId);
+               foreach ($shares as $share) {
+                       $acl[] = [
+                               'privilege' => '{DAV:}read',
+                               'principal' => $share['{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
+                               'protected' => true,
+                       ];
+                       if (!$share['readOnly']) {
+                               $acl[] = [
+                                       'privilege' => '{DAV:}write',
+                                       'principal' => $share['{' . \OCA\DAV\CardDAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
+                                       'protected' => true,
+                               ];
+                       }
+               }
+               return $acl;
+       }
 }
index 7ad3f43dca869114cba5ec568fb9e524f01257a9..d25b84d01f359bf7970bca8a5cba8bd063cbdad1 100644 (file)
@@ -34,6 +34,8 @@ use Sabre\HTTP\ResponseInterface;
 
 class Plugin extends ServerPlugin {
 
+       const NS_OWNCLOUD = 'http://owncloud.org/ns';
+
        /** @var Auth */
        private $auth;
 
@@ -100,7 +102,7 @@ class Plugin extends ServerPlugin {
        function initialize(Server $server) {
                $this->server = $server;
                $server->resourceTypeMapping['OCA\\DAV\CardDAV\\ISharedAddressbook'] = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}shared';
-               $this->server->xml->elementMap['{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share'] = 'OCA\\DAV\\CardDAV\\Sharing\\Xml\\ShareRequest';
+               $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = 'OCA\\DAV\\CardDAV\\Sharing\\Xml\\ShareRequest';
 
                $this->server->on('method:POST', [$this, 'httpPost']);
        }
@@ -148,7 +150,7 @@ class Plugin extends ServerPlugin {
 
                        // Dealing with the 'share' document, which modified invitees on a
                        // calendar.
-                       case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share' :
+                       case '{' . self::NS_OWNCLOUD . '}share' :
 
                                // We can only deal with IShareableCalendar objects
                                if (!$node instanceof IShareableAddressBook) {
index 6be6bd795a1af23178f15471fc9bdb16ce8cca05..bd55dd4073e8feae8a421fa1f95eabeeb8d0e392 100644 (file)
@@ -20,6 +20,7 @@
  */
 namespace OCA\DAV\CardDAV\Sharing\Xml;
 
+use OCA\DAV\CardDAV\Sharing\Plugin;
 use Sabre\Xml\Reader;
 use Sabre\Xml\XmlDeserializable;
 
@@ -44,32 +45,32 @@ class ShareRequest implements XmlDeserializable {
 
     static function xmlDeserialize(Reader $reader) {
 
-        $elems = $reader->parseInnerTree([
-            '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV. '}set'    => 'Sabre\\Xml\\Element\\KeyValue',
-            '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
+        $elements = $reader->parseInnerTree([
+            '{' . Plugin::NS_OWNCLOUD. '}set'    => 'Sabre\\Xml\\Element\\KeyValue',
+            '{' . Plugin::NS_OWNCLOUD . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
         ]);
 
         $set = [];
         $remove = [];
 
-        foreach ($elems as $elem) {
+        foreach ($elements as $elem) {
             switch ($elem['name']) {
 
-                case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}set' :
+                case '{' . Plugin::NS_OWNCLOUD . '}set' :
                     $sharee = $elem['value'];
 
-                    $sumElem = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}summary';
-                    $commonName = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}common-name';
+                    $sumElem = '{' . Plugin::NS_OWNCLOUD . '}summary';
+                    $commonName = '{' . Plugin::NS_OWNCLOUD . '}common-name';
 
                     $set[] = [
                         'href'       => $sharee['{DAV:}href'],
                         'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null,
                         'summary'    => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
-                        'readOnly'   => !array_key_exists('{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}read-write', $sharee),
+                        'readOnly'   => !array_key_exists('{' . Plugin::NS_OWNCLOUD . '}read-write', $sharee),
                     ];
                     break;
 
-                case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}remove' :
+                case '{' . Plugin::NS_OWNCLOUD . '}remove' :
                     $remove[] = $elem['value']['{DAV:}href'];
                     break;
 
diff --git a/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd b/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd
deleted file mode 100644 (file)
index d642f4f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
- Copyright (c) 2006-2015 Apple Inc. All rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<!ELEMENT serverinfo (host, path, nonsslport, sslport, unix?,
-                                               host2?, nonsslport2?, sslport2?, unix2?,
-                                               authtype?, waitcount?, waitdelay?, waitsuccess?,
-                                               features?, substitutions)? >
-
-       <!ELEMENT host                  (#PCDATA)>
-       <!ELEMENT path                  (#PCDATA)>
-       <!ELEMENT nonsslport    (#PCDATA)>
-       <!ELEMENT sslport               (#PCDATA)>
-       <!ELEMENT unix                  (#PCDATA)>
-       <!ELEMENT host2                 (#PCDATA)>
-       <!ELEMENT nonsslport2   (#PCDATA)>
-       <!ELEMENT sslport2              (#PCDATA)>
-       <!ELEMENT unix2                 (#PCDATA)>
-       <!ELEMENT authtype              (#PCDATA)>
-       <!ELEMENT waitdelay     (#PCDATA)>
-       <!ELEMENT waitcount     (#PCDATA)>
-       <!ELEMENT waitsuccess   (#PCDATA)>
-       <!ELEMENT features      (feature*)>
-               <!ELEMENT feature   (#PCDATA)>
-       <!ELEMENT substitutions (substitution|repeat)*>
-               <!ELEMENT repeat        (substitution+)>
-               <!ATTLIST repeat count CDATA "1">
-               <!ELEMENT substitution  (key, value)>
-                       <!ELEMENT key                   (#PCDATA)>
-                       <!ELEMENT value                 (#PCDATA)>
-       
diff --git a/apps/dav/tests/travis/caldavtest/config/serverinfo.xml b/apps/dav/tests/travis/caldavtest/config/serverinfo.xml
deleted file mode 100644 (file)
index c80e47f..0000000
+++ /dev/null
@@ -1,854 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!DOCTYPE serverinfo SYSTEM
-               "/home/deepdiver/Development/ownCloud/master/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd">
-
-<!--
- Copyright (c) 2006-2015 Apple Inc. All rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<serverinfo>
-       <host>localhost</host>
-       <nonsslport>8888</nonsslport>
-       <authtype>basic</authtype>
-       <!-- <unix>/tmp/caldavd_requests/unsecured.sock</unix> -->
-
-       <waitcount>120</waitcount>
-       <waitdelay>0.25</waitdelay>
-       <waitsuccess>30</waitsuccess>
-
-       <features>
-               <!--  Generic WebDAV extensions -->
-               <feature>COPY Method</feature>                                                  <!-- COPY method -->
-               <feature>MOVE Method</feature>                                                  <!-- MOVE method -->
-               <feature>Extended MKCOL</feature>                                               <!-- Extended MKCOL -->
-
-               <!-- ACL related -->
-               <feature>ACL Method</feature>                                                   <!-- ACL method -->
-               <feature>acl-principal-prop-set REPORT</feature>                <!-- ACL acl-principal-prop-set REPORT -->
-               <feature>principal-match REPORT</feature>                               <!-- ACL principal-match REPORT -->
-               <feature>principal-property-search REPORT</feature>             <!-- ACL principal-property-search REPORT -->
-               <feature>principal-search-property-set REPORT</feature> <!-- ACL principal-search-property-set REPORT -->
-               <feature>calendarserver-principal-search REPORT</feature>       <!-- ACL calendarserver-principal-search REPORT -->
-
-               <feature>add-member</feature>                                   <!-- Add-member used to create resources -->
-               <!-- <feature>auth-on-root</feature> -->                <!-- Whether the server requires authentication on the root URI -->
-               <feature>brief</feature>                                            <!-- Brief header for PROPFIND, REPORT -->
-               <feature>bulk-post</feature>                                    <!-- Bulk POST requests -->
-               <feature>ctag</feature>                                                 <!-- ctag extension -->
-               <feature>current-user-principal</feature>               <!-- current-user-principal extension -->
-               <feature>directory listing</feature>                    <!-- GET on collection -->
-               <feature>extended-principal-search</feature>    <!-- Extended principal-property-search REPORT extension -->
-               <feature>expand-property</feature>                              <!-- Expand property REPORT -->
-               <feature>only-proxy-groups</feature>                    <!-- Group-membership only includes delegated-to groups -->
-               <feature>limits</feature>                                               <!-- max-collections and max-resources limits -->
-               <feature>own-root</feature>                                             <!-- / is owned by this service -->
-               <feature>prefer</feature>                                               <!-- Prefer header overall support -->
-               <feature>prefer-minimal</feature>                               <!-- Prefer header return=minimal -->
-               <feature>prefer-representation</feature>                <!-- Prefer header return=representation -->
-               <feature>prefer-noroot</feature>                                <!-- Prefer header depth-noroot -->
-               <feature>quota</feature>                                                <!-- WebDAV QUOTA -->
-               <!-- <feature>quota-on-resources</feature> -->  <!-- WebDAV QUOTA on calendar and address book object resources -->
-               <feature>resource-id</feature>                                  <!-- WebDAV BIND DAV:resource-id property -->
-               <feature>sync-report</feature>                                  <!-- WebDAV collection sync REPORT -->
-               <!-- <feature>sync-report-limit</feature> -->   <!-- WebDAV collection sync REPORT DAV:limit support -->
-               <feature>sync-report-home</feature>                             <!-- WebDAV collection sync REPORT on Homes -->
-               <feature>sync-report-config-token</feature>             <!-- Sync REPORT token includes configuration component -->
-               <feature>well-known</feature>                                   <!-- well-known feature -->
-
-               <!-- <feature>per-object-ACLs</feature> -->             <!-- ACL for objects in calendar/address books -->
-               <!-- <feature>regular-collection</feature> -->  <!-- Regular collections allowed in calendar/address book homes -->
-
-               <feature>json-data</feature>                                    <!-- jCal and jCard support -->
-
-               <!--  CalendarServer specific extensions -->
-               <feature>control-api</feature>                                  <!-- Control API support -->
-
-               <!-- CalDAV specific extension -->
-               <feature>caldav</feature>                                           <!-- Basic CalDAV feature enabler -->
-               <feature>attachments-collection</feature>               <!-- Server uses a collection in same WebDAV tree to store attachments -->
-               <feature>auto-accept</feature>                                  <!-- Auto-accept for rooms & locations -->
-               <feature>auto-accept-modes</feature>                    <!-- Auto-accept modes -->
-               <feature>client-fix-TRANSP</feature>                    <!-- fix client TRANSP -->
-               <!-- <feature>dropbox</feature> -->                             <!-- dropbox extension -->
-               <feature>default-alarms</feature>                               <!-- default alarms extension -->
-               <feature>EMAIL parameter</feature>                              <!-- Server normalizes cuaddress and adds EMAIL parameter -->
-               <feature>extended-freebusy</feature>            <!-- Extended freebusy response -->
-               <feature>freebusy-url</feature>                         <!-- Freebusy URL -->
-               <feature>group-attendee-expansion</feature>         <!-- Auto-expansion of group attendees -->
-               <feature>implicit-scheduling</feature>                  <!-- CalDAV scheduling - implicit -->
-               <feature>location-resource-tracking</feature>   <!-- Server tracks who makes unscheduled changes to locations and resources -->
-               <feature>managed-attachments</feature>                  <!-- CalDAV Managed Attachments -->
-               <feature>maskuid</feature>                                              <!-- maskuid extension -->
-               <feature>no-duplicate-uids</feature>                    <!-- duplicate UIDs in same home not supported -->
-               <feature>partstat-timestamp</feature>                   <!-- Time stamps when PARTSTAT changes extension -->
-               <!-- <feature>podding</feature> -->                     <!-- Podded server -->
-               <feature>private-comments</feature>                             <!-- private-comments extension -->
-               <feature>private-events</feature>                               <!-- private-events extension -->
-               <feature>proxy</feature>                                                <!-- calendar-user-proxy extension -->
-               <!-- <feature>proxy-authz</feature> -->                 <!-- sudo user extension -->
-               <feature>recurrence-splitting</feature>                 <!-- Recurring components can be split -->
-               <feature>remove-duplicate-alarms</feature>      <!-- Server removes any duplicate alarms on PUT -->
-               <feature>query-extended</feature>                               <!-- calendar-query-extended extension -->
-               <feature>shared-calendars</feature>                             <!-- Shared calendars extension -->
-               <feature>share-calendars-to-groups</feature>    <!-- Share calendars to groups extension -->
-               <feature>schedule-changes</feature>                             <!-- schedule-changes property extension -->
-               <feature>split-calendars</feature>                              <!-- Calendars are split by component type -->
-               <feature>supported-component-sets</feature>             <!-- CALDAV:supported-calendar-component-sets on calendar homes -->
-               <feature>supported-component-sets-one</feature> <!-- Only single component calendars allowed to be created -->
-               <feature>timerange-low-limit</feature>                  <!-- Time-range only valid one year back -->
-               <feature>timerange-high-limit</feature>                 <!-- Time-range only valid 5 years ahead -->
-               <feature>timezones-by-reference</feature>               <!-- Timezones by reference enabled -->
-               <feature>timezone-service</feature>                             <!-- Timezone service extension for Wiki -->
-               <feature>timezone-std-service</feature>                 <!-- Timezone standard service extension -->
-               <!-- <feature>trash-collection</feature> -->                    <!-- Trash collection enabled -->
-               <feature>travel-time-busy</feature>                     <!-- Travel time appears as busy -->
-               <feature>vavailability</feature>                                <!-- VAVAILABILITY on inbox -->
-               <!-- <feature>vpoll</feature> -->                               <!-- VPOLL support for store and scheduling -->
-               <feature>webcal</feature>                                               <!-- Internet calendar subscription via GET on calendar collection -->
-
-               <!-- CardDAV specific extension -->
-               <feature>carddav</feature>                                              <!-- Basic CardDAV feature enabler -->
-               <feature>default-addressbook</feature>                  <!-- Default address book behavior -->
-               <feature>shared-addressbooks</feature>                  <!-- Shared address books extension -->
-               <feature>shared-addressbook-groups</feature>    <!-- Shared address book groups extension -->
-               <feature>directory-gateway</feature>                    <!-- Directory gateway extension -->
-
-       </features>
-
-       <substitutions>
-               <!-- Useful xpath shortcuts for verifiers -->
-               <substitution>
-                       <key>$multistatus-response-prefix:</key>
-                       <value>/{DAV:}multistatus/{DAV:}response</value>
-               </substitution>
-               <substitution>
-                       <key>$multistatus-href-prefix:</key>
-                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}href</value>
-               </substitution>
-               <substitution>
-                       <key>$verify-response-prefix:</key>
-                       <value>{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
-               </substitution>
-               <substitution>
-                       <key>$verify-property-prefix:</key>
-                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
-               </substitution>
-               <substitution>
-                       <key>$verify-bad-response:</key>
-                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}status</value>
-               </substitution>
-               <substitution>
-                       <key>$verify-error-response:</key>
-                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}error</value>
-               </substitution>
-               <substitution>
-                       <key>$CALDAV:</key>
-                       <value>urn:ietf:params:xml:ns:caldav</value>
-               </substitution>
-               <substitution>
-                       <key>$CARDDAV:</key>
-                       <value>urn:ietf:params:xml:ns:carddav</value>
-               </substitution>
-               <substitution>
-                       <key>$CS:</key>
-                       <value>http://calendarserver.org/ns/</value>
-               </substitution>
-
-               <!-- Server configuration settings -->
-               <!-- $host: and $hostssl: are implicitly added by CalDAVTester based
-                    on the host/nonsslport/sslport values and ssl command line switch -->
-
-               <!-- relative path to caldav root-->
-               <substitution>
-                       <key>$root:</key>
-                       <value>/remote.php/dav/</value>
-               </substitution>
-
-               <!-- relative path to main principal collection-->
-               <substitution>
-                       <key>$principalcollection:</key>
-                       <value>$root:principals/users/</value>
-               </substitution>
-
-               <!-- the core recored type collections-->
-               <substitution>
-                       <key>$uidstype:</key>
-                       <value>__uids__</value>
-               </substitution>
-               <substitution>
-                       <key>$userstype:</key>
-                       <value>users</value>
-               </substitution>
-               <substitution>
-                       <key>$groupstype:</key>
-                       <value>groups</value>
-               </substitution>
-               <substitution>
-                       <key>$locationstype:</key>
-                       <value>locations</value>
-               </substitution>
-               <substitution>
-                       <key>$resourcestype:</key>
-                       <value>resources</value>
-               </substitution>
-
-               <!-- relative path to record type principal collections-->
-               <substitution>
-                       <key>$principals_uids:</key>
-                       <value>$principalcollection:$uidstype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$principals_users:</key>
-                       <value>$principalcollection:$userstype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$principals_groups:</key>
-                       <value>$principalcollection:$groupstype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$principals_resources:</key>
-                       <value>$principalcollection:$resourcestype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$principals_locations:</key>
-                       <value>$principalcollection:$locationstype:/</value>
-               </substitution>
-
-               <!-- relative path to calendars collection-->
-               <substitution>
-                       <key>$calendars:</key>
-                       <value>$root:calendars/</value>
-               </substitution>
-
-               <!-- relative path to record type calendar collections-->
-               <substitution>
-                       <key>$calendars_uids:</key>
-                       <value>$calendars:$uidstype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$calendars_users:</key>
-                       <value>$calendars:$userstype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$calendars_resources:</key>
-                       <value>$calendars:$resourcestype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$calendars_locations:</key>
-                       <value>$calendars:$locationstype:/</value>
-               </substitution>
-
-               <!-- primary calendar name-->
-               <substitution>
-                       <key>$calendar:</key>
-                       <value>calendar</value>
-               </substitution>
-
-               <!-- primary tasks-only calendar name-->
-               <substitution>
-                       <key>$tasks:</key>
-                       <value>tasks</value>
-               </substitution>
-
-               <!-- primary polls-only calendar name-->
-               <substitution>
-                       <key>$polls:</key>
-                       <value>polls</value>
-               </substitution>
-
-               <!-- inbox name-->
-               <substitution>
-                       <key>$inbox:</key>
-                       <value>inbox</value>
-               </substitution>
-
-               <!-- outbox name-->
-               <substitution>
-                       <key>$outbox:</key>
-                       <value>outbox</value>
-               </substitution>
-
-               <!-- dropbox name-->
-               <substitution>
-                       <key>$dropbox:</key>
-                       <value>dropbox</value>
-               </substitution>
-
-               <!-- attachments name-->
-               <substitution>
-                       <key>$attachments:</key>
-                       <value>dropbox</value>
-               </substitution>
-
-               <!-- notification name-->
-               <substitution>
-                       <key>$notification:</key>
-                       <value>notification</value>
-               </substitution>
-
-               <!-- freebusy name-->
-               <substitution>
-                       <key>$freebusy:</key>
-                       <value>freebusy</value>
-               </substitution>
-
-               <!-- Sync home collection items - use "-" to include the home resource-->
-               <substitution>
-                       <key>$calendar_home_items_initial_sync:</key>
-                       <value>[-,$calendar:/,$tasks:/,$inbox:/,$outbox:/,$freebusy:,$notification:/]</value>
-               </substitution>
-
-               <!-- Sync collection extra items - use "-" to include the collection-->
-               <substitution>
-                       <key>$calendar_sync_extra_items:</key>
-                       <value>[-]</value>
-               </substitution>
-
-               <!-- Sync collection extra count - gets added to the totalcount value-->
-               <substitution>
-                       <key>$calendar_sync_extra_count:</key>
-                       <value>1</value> <!-- the request-uri resource is returned when no token passed-->
-               </substitution>
-
-               <!-- server-to-server inbox-->
-               <substitution>
-                       <key>$servertoserver:</key>
-                       <value>$root:inbox</value>
-               </substitution>
-
-               <!-- timezone service-->
-               <substitution>
-                       <key>$timezoneservice:</key>
-                       <value>$root:timezones</value>
-               </substitution>
-
-               <!-- timezone std service-->
-               <substitution>
-                       <key>$timezonestdservice:</key>
-                       <value>$root:stdtimezones</value>
-               </substitution>
-
-               <!-- relative path to addressbooks collection-->
-               <substitution>
-                       <key>$addressbooks:</key>
-                       <value>$root:addressbooks/</value>
-               </substitution>
-
-               <!-- relative path to record type addressbook collections-->
-               <substitution>
-                       <key>$addressbooks_uids:</key>
-                       <value>$addressbooks:$uidstype:/</value>
-               </substitution>
-               <substitution>
-                       <key>$addressbooks_users:</key>
-                       <value>$addressbooks:$userstype:/</value>
-               </substitution>
-
-               <!-- primary addressbook name -->
-               <substitution>
-                       <key>$addressbook:</key>
-                       <value>addressbook</value>
-               </substitution>
-
-               <!-- directory name -->
-               <substitution>
-                       <key>$directory:</key>
-                       <value>$root:directory/</value>
-               </substitution>
-
-               <!-- POST add-member URI suffix -->
-               <substitution>
-                       <key>$add-member:</key>
-                       <value>;add-member</value>
-               </substitution>
-
-               <!-- user id for admin user -->
-               <substitution>
-                       <key>$useradmin:</key>
-                       <value>admin</value>
-               </substitution>
-               <!-- guid for admin user -->
-               <substitution>
-                       <key>$useradminguid:</key>
-                       <value>0C8BDE62-E600-4696-83D3-8B5ECABDFD2E</value>
-               </substitution>
-               <!-- password for admin user -->
-               <substitution>
-                       <key>$pswdadmin:</key>
-                       <value>admin</value>
-               </substitution>
-
-               <!-- relative path to admin principal resource-->
-               <substitution>
-                       <key>$principal_admin:</key>
-                       <value>$principals_users:$useradmin:/</value>
-               </substitution>
-               <substitution>
-                       <key>$principaluri_admin:</key>
-                       <value>$principals_uids:$useradminguid:/</value>
-               </substitution>
-
-               <!-- user id for apprentice user -->
-               <substitution>
-                       <key>$userapprentice:</key>
-                       <value>apprentice</value>
-               </substitution>
-               <!-- guid for apprentice user -->
-               <substitution>
-                       <key>$userapprenticeguid:</key>
-                       <value>29B6C503-11DF-43EC-8CCA-40C7003149CE</value>
-               </substitution>
-               <!-- password for admin user -->
-               <substitution>
-                       <key>$pswdapprentice:</key>
-                       <value>apprentice</value>
-               </substitution>
-
-               <!-- relative path to apprentice principal resource-->
-               <substitution>
-                       <key>$principal_apprentice:</key>
-                       <value>$principals_users:$userapprentice:/</value>
-               </substitution>
-               <substitution>
-                       <key>$principaluri_apprentice:</key>
-                       <value>$principals_uids:$userapprenticeguid:/</value>
-               </substitution>
-
-               <!-- user id for proxy user -->
-               <substitution>
-                       <key>$userproxy:</key>
-                       <value>superuser</value>
-               </substitution>
-               <!-- password for proxy user -->
-               <substitution>
-                       <key>$pswdproxy:</key>
-                       <value>superuser</value>
-               </substitution>
-
-               <!--  Forty user accounts -->
-               <repeat count="40">
-                       <!-- user id -->
-                       <substitution>
-                               <key>$userid%d:</key>
-                               <value>user%02d</value>
-                       </substitution>
-                       <!-- user guid -->
-                       <substitution>
-                               <key>$userguid%d:</key>
-                               <value>10000000-0000-0000-0000-000000000%03d</value>
-                       </substitution>
-                       <!-- user name -->
-                       <substitution>
-                               <key>$username%d:</key>
-                               <value>User %02d</value>
-                       </substitution>
-                       <!-- user name URI encoded -->
-                       <substitution>
-                               <key>$username-encoded%d:</key>
-                               <value>User%%20%02d</value>
-                       </substitution>
-                       <!-- first name -->
-                       <substitution>
-                               <key>$firstname%d:</key>
-                               <value>User</value>
-                       </substitution>
-                       <!-- last name -->
-                       <substitution>
-                               <key>$lastname%d:</key>
-                               <value>%02d</value>
-                       </substitution>
-                       <!-- password -->
-                       <substitution>
-                               <key>$pswd%d:</key>
-                               <value>user%02d</value>
-                       </substitution>
-                       <!-- relative path to user principal resource-->
-                       <substitution>
-                               <key>$principal%d:</key>
-                               <value>$principals_users:$userid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$principaluri%d:</key>
-                               <value>$principalcollection:$userid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$principal%dnoslash:</key>
-                               <value>$principals_users:$userid%d:</value>
-                       </substitution>
-
-                       <!-- relative path to user calendar home-->
-                       <substitution>
-                               <key>$calendarhome%d:</key>
-                               <value>$calendars_uids:$userguid%d:</value>
-                       </substitution>
-                       <!-- relative path to user alternate calendar home-->
-                       <substitution>
-                               <key>$calendarhomealt%d:</key>
-                               <value>$calendars_users:$userid%d:</value>
-                       </substitution>
-                       <!-- relative path to user calendar-->
-                       <substitution>
-                               <key>$calendarpath%d:</key>
-                               <value>$calendarhome%d:/$calendar:</value>
-                       </substitution>
-                       <!-- relative path to user alternate calendar-->
-                       <substitution>
-                               <key>$calendarpathalt%d:</key>
-                               <value>$calendarhomealt%d:/$calendar:</value>
-                       </substitution>
-                       <!-- relative path to user tasks calendar-->
-                       <substitution>
-                               <key>$taskspath%d:</key>
-                               <value>$calendarhome%d:/$tasks:</value>
-                       </substitution>
-                       <!-- relative path to user polls calendar-->
-                       <substitution>
-                               <key>$pollspath%d:</key>
-                               <value>$calendarhome%d:/$polls:</value>
-                       </substitution>
-                       <!-- relative path to user inbox-->
-                       <substitution>
-                               <key>$inboxpath%d:</key>
-                               <value>$calendarhome%d:/$inbox:</value>
-                       </substitution>
-                       <!-- relative path to user outbox-->
-                       <substitution>
-                               <key>$outboxpath%d:</key>
-                               <value>$calendarhome%d:/$outbox:</value>
-                       </substitution>
-                       <!-- relative path to user dropbox-->
-                       <substitution>
-                               <key>$dropboxpath%d:</key>
-                               <value>$calendarhome%d:/$dropbox:</value>
-                       </substitution>
-                       <!-- relative path to user notification-->
-                       <substitution>
-                               <key>$notificationpath%d:</key>
-                               <value>$calendarhome%d:/$notification:</value>
-                       </substitution>
-                       <!-- relative path to user freebusy-->
-                       <substitution>
-                               <key>$freebusypath%d:</key>
-                               <value>$calendarhome%d:/$freebusy:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$email%d:</key>
-                               <value>$userid%d:@example.com</value>
-                       </substitution>
-                       <!-- calendar user address of user-->
-                       <substitution>
-                               <key>$cuaddr%d:</key>
-                               <value>mailto:$email%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$cuaddralt%d:</key>
-                               <value>$cuaddr%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$cuaddraltnoslash%d:</key>
-                               <value>$cuaddr%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$cuaddrurn%d:</key>
-                               <value>urn:x-uid:$userguid%d:</value>
-                       </substitution>
-
-                       <!-- relative path to user addressbook home-->
-                       <substitution>
-                               <key>$addressbookhome%d:</key>
-                               <value>$addressbooks:users/$userid%d:</value>
-                       </substitution>
-                       <!-- relative path to user addressbook-->
-                       <substitution>
-                               <key>$addressbookpath%d:</key>
-                               <value>$addressbookhome%d:/$addressbook:</value>
-                       </substitution>
-               </repeat>
-
-               <!--  Ten public accounts -->
-               <repeat count="10">
-                       <!-- user id -->
-                       <substitution>
-                               <key>$publicuserid%d:</key>
-                               <value>public%02d</value>
-                       </substitution>
-                       <!-- user guid -->
-                       <substitution>
-                               <key>$publicuserguid%d:</key>
-                               <value>50000000-0000-0000-0000-0000000000%02d</value>
-                       </substitution>
-                       <!-- user name -->
-                       <substitution>
-                               <key>$publicusername%d:</key>
-                               <value>Public %02d</value>
-                       </substitution>
-                       <!-- password -->
-                       <substitution>
-                               <key>$publicpswd%d:</key>
-                               <value>public%02d</value>
-                       </substitution>
-                       <!-- relative path to user principal resource-->
-                       <substitution>
-                               <key>$publicprincipal%d:</key>
-                               <value>$principals_users:$publicuserid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$publicprincipaluri%d:</key>
-                               <value>$principals_uids:$publicuserguid%d:/</value>
-                       </substitution>
-                       <!-- relative path to user calendar home-->
-                       <substitution>
-                               <key>$publiccalendarhome%d:</key>
-                               <value>$calendars_uids:$publicuserguid%d:</value>
-                       </substitution>
-                       <!-- relative path to user calendar-->
-                       <substitution>
-                               <key>$publiccalendarpath%d:</key>
-                               <value>$calendars_uids:$publicuserguid%d:/$calendar:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$publicemail%d:</key>
-                               <value>$publicuserid%d:@example.com</value>
-                       </substitution>
-                       <!-- calendar user address of user-->
-                       <substitution>
-                               <key>$publiccuaddr%d:</key>
-                               <value>mailto:$publicemail%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$publiccuaddralt%d:</key>
-                               <value>$publiccuaddr%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$publiccuaddrurn%d:</key>
-                               <value>urn:x-uid:$publicuserguid%d:</value>
-                       </substitution>
-               </repeat>
-
-               <!--  Twenty resource accounts -->
-               <repeat count="20">
-                       <substitution>
-                               <key>$resourceid%d:</key>
-                               <value>resource%02d</value>
-                       </substitution>
-                       <!-- resource guid-->
-                       <substitution>
-                               <key>$resourceguid%d:</key>
-                               <value>40000000-0000-0000-0000-000000000%03d</value>
-                       </substitution>
-                       <!-- resource name-->
-                       <substitution>
-                               <key>$resourcename%d:</key>
-                               <value>Resource %02d</value>
-                       </substitution>
-                       <!-- relative path to first resource calendar home-->
-                       <substitution>
-                               <key>$rcalendarhome%d:</key>
-                               <value>$calendars_uids:$resourceguid%d:</value>
-                       </substitution>
-                       <!-- relative path to first resource calendar home-->
-                       <substitution>
-                               <key>$rcalendarpath%d:</key>
-                               <value>$calendars_uids:$resourceguid%d:/$calendar:</value>
-                       </substitution>
-                       <!-- relative path to first resource inbox-->
-                       <substitution>
-                               <key>$rinboxpath%d:</key>
-                               <value>$calendars_uids:$resourceguid%d:/$inbox:</value>
-                       </substitution>
-                       <!-- relative path to first resource outbox-->
-                       <substitution>
-                               <key>$routboxpath%d:</key>
-                               <value>$calendars_uids:$resourceguid%d:/$outbox:</value>
-                       </substitution>
-                       <!-- relative path to first resource principal resource-->
-                       <substitution>
-                               <key>$rprincipal%d:</key>
-                               <value>$principals_resources:$resourceid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$rprincipaluri%d:</key>
-                               <value>$principals_uids:$resourceguid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$rcuaddralt%d:</key>
-                               <value>$rcuaddrurn%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$rcuaddrurn%d:</key>
-                               <value>urn:x-uid:$resourceguid%d:</value>
-                       </substitution>
-               </repeat>
-
-               <!--  Ten Location accounts -->
-               <repeat count="10">
-                       <substitution>
-                               <key>$locationid%d:</key>
-                               <value>location%02d</value>
-                       </substitution>
-                       <!-- location guid-->
-                       <substitution>
-                               <key>$locationguid%d:</key>
-                               <value>30000000-0000-0000-0000-000000000%03d</value>
-                       </substitution>
-                       <!-- location name-->
-                       <substitution>
-                               <key>$locationname%d:</key>
-                               <value>Location %02d</value>
-                       </substitution>
-                       <!-- relative path to first location calendar home-->
-                       <substitution>
-                               <key>$lcalendarhome%d:</key>
-                               <value>$calendars_uids:$locationguid%d:</value>
-                       </substitution>
-                       <!-- relative path to first location calendar home-->
-                       <substitution>
-                               <key>$lcalendarpath%d:</key>
-                               <value>$calendars_uids:$locationguid%d:/$calendar:</value>
-                       </substitution>
-                       <!-- relative path to first location inbox-->
-                       <substitution>
-                               <key>$linboxpath%d:</key>
-                               <value>$calendars_uids:$locationguid%d:/$inbox:</value>
-                       </substitution>
-                       <!-- relative path to first location outbox-->
-                       <substitution>
-                               <key>$loutboxpath%d:</key>
-                               <value>$calendars_uids:$locationguid%d:/$outbox:</value>
-                       </substitution>
-                       <!-- relative path to first location principal resource-->
-                       <substitution>
-                               <key>$lprincipal%d:</key>
-                               <value>$principals_resources:$locationid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$lprincipaluri%d:</key>
-                               <value>$principals_uids:$locationguid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$lcuaddralt%d:</key>
-                               <value>$lprincipaluri%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$lcuaddrurn%d:</key>
-                               <value>urn:x-uid:$locationguid%d:</value>
-                       </substitution>
-               </repeat>
-
-
-               <!--  Ten Group accounts -->
-               <repeat count="40">
-                       <substitution>
-                               <key>$groupid%d:</key>
-                               <value>group%02d</value>
-                       </substitution>
-                       <!-- group guid-->
-                       <substitution>
-                               <key>$groupguid%d:</key>
-                               <value>20000000-0000-0000-0000-000000000%03d</value>
-                       </substitution>
-                       <!-- group name-->
-                       <substitution>
-                               <key>$groupname%d:</key>
-                               <value>Group %02d</value>
-                       </substitution>
-                       <!-- relative path to first group principal resource-->
-                       <substitution>
-                               <key>$gprincipal%d:</key>
-                               <value>$principals_resources:$groupid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$gprincipaluri%d:</key>
-                               <value>$principals_uids:$groupguid%d:/</value>
-                       </substitution>
-                       <substitution>
-                               <key>$gemail%d:</key>
-                               <value>$groupid%d:@example.com</value>
-                       </substitution>
-                       <substitution>
-                               <key>$gcuaddralt%d:</key>
-                               <value>$gprincipaluri%d:</value>
-                       </substitution>
-                       <substitution>
-                               <key>$gcuaddrurn%d:</key>
-                               <value>urn:x-uid:$groupguid%d:</value>
-                       </substitution>
-               </repeat>
-
-               <!--  User with non-ascii name -->
-               <substitution>
-                       <key>$i18nid:</key>
-                       <value>i18nuser</value>
-               </substitution>
-               <!-- group guid-->
-               <substitution>
-                       <key>$i18nguid:</key>
-                       <value>860B3EE9-6D7C-4296-9639-E6B998074A78</value>
-               </substitution>
-               <!-- group name-->
-               <substitution>
-                       <key>$i18nname:</key>
-                       <value>まだ</value>
-               </substitution>
-               <!-- password -->
-               <substitution>
-                       <key>$i18npswd:</key>
-                       <value>i18nuser</value>
-               </substitution>
-               <!-- relative path to user calendar-->
-               <substitution>
-                       <key>$i18ncalendarpath:</key>
-                       <value>$calendars_uids:$i18nguid:/$calendar:</value>
-               </substitution>
-               <substitution>
-                       <key>$i18nemail:</key>
-                       <value>$i18nid:@example.com</value>
-               </substitution>
-               <!-- CUAddrs -->
-               <substitution>
-                       <key>$i18ncuaddr:</key>
-                       <value>mailto:$i18nemail:</value>
-               </substitution>
-               <substitution>
-                       <key>$i18ncuaddrurn:</key>
-                       <value>urn:x-uid:$i18nguid:</value>
-               </substitution>
-
-               <!-- relative path to disabled group principal resource-->
-               <substitution>
-                       <key>$principaldisabled:</key>
-                       <value>$principals_groups:disabledgroup/</value>
-               </substitution>
-               <substitution>
-                       <key>$principaluridisabled:</key>
-                       <value>$principals_uids:disabledgroup/</value>
-               </substitution>
-               <!-- calendar user address of disabled group-->
-               <substitution>
-                       <key>$cuaddrdisabled:</key>
-                       <value>$principals_uids:disabledgroup/</value>
-               </substitution>
-
-               <!--  Override some of the above definitions for special cases -->
-
-               <!-- calendar user address of second user-->
-               <substitution>
-                       <key>$cuaddr2:</key>
-                       <value>MAILTO:$email2:</value>
-               </substitution>
-
-       </substitutions>
-</serverinfo>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/1.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/1.xml
new file mode 100644 (file)
index 0000000..20d2ebf
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://owncloud.org/ns">
+    <CS:set>
+        <D:href>principal:principals/users/user02</D:href>
+        <CS:summary>My Shared Calendar</CS:summary>
+        <CS:read-write/>
+    </CS:set>
+</CS:share>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/4.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/4.xml
new file mode 100644 (file)
index 0000000..fd0f248
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:">
+<D:prop>
+<D:resourcetype/>
+<D:owner/>
+<D:current-user-privilege-set/>
+</D:prop>
+</D:propfind>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/6.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/6.vcf
new file mode 100644 (file)
index 0000000..6b53f8b
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;TYPE=INTERNET,WORK,pref:lthompson@example.com
+TEL;TYPE=WORK,pref:1-555-555-5555
+TEL;TYPE=CELL:1-555-555-5555
+ITEM1.ADR;TYPE=WORK,pref:;;2 Lag;Elk Forest;California;99999;USA
+ITEM1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1:ABPerson
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/7.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/7.vcf
new file mode 100644 (file)
index 0000000..27fdb9f
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;TYPE=INTERNET,WORK,pref:lthompson@example.net
+TEL;TYPE=WORK,pref:1-555-555-5555
+TEL;TYPE=CELL:1-555-555-6666
+ITEM1.ADR;TYPE=WORK,pref:;;2 Lag;Elk Forest;California;99999;USA
+ITEM1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1:ABPerson
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/8.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/8.vcf
new file mode 100644 (file)
index 0000000..9188fdd
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Miller;Default;;;
+FN:Default Miller
+EMAIL;TYPE=INTERNET,WORK,pref:lthompson@example.com
+TEL;TYPE=WORK,pref:1-555-555-5555
+TEL;TYPE=CELL:1-555-555-5555
+ITEM1.ADR;TYPE=WORK,pref:;;2 Lag;Elk Forest;California;99999;USA
+ITEM1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1:ABPerson
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/9.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/sharing/read-write/9.vcf
new file mode 100644 (file)
index 0000000..1ca0a36
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Smith;Default;;;
+FN:Default Smith
+EMAIL;TYPE=INTERNET,WORK,pref:lthompson@example.com
+TEL;TYPE=WORK,pref:1-555-555-5555
+TEL;TYPE=CELL:1-555-555-5555
+ITEM1.ADR;TYPE=WORK,pref:;;2 Lag;Elk Forest;California;99999;USA
+ITEM1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1:ABPerson
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vcurrent-user-principal/1.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vcurrent-user-principal/1.xml
new file mode 100644 (file)
index 0000000..dffedc6
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:">
+<D:prop>
+<D:current-user-principal/>
+</D:prop>
+</D:propfind>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/1.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/1.vcf
new file mode 100644 (file)
index 0000000..2121c65
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson@example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-555-555-5555
+item1.ADR;type=WORK;type=pref:;;2 Lag;Elk Forest;California;99999;USA
+item1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1:ABPerson
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/2.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/2.vcf
new file mode 100644 (file)
index 0000000..390a3d8
--- /dev/null
@@ -0,0 +1,17 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Contact;Mulberry;;;
+FN:Mulberry Contact
+NICKNAME:mulberry
+ORG:Apple Inc.;
+EMAIL;type=INTERNET;type=WORK;type=pref:mulberry_contact@example.com
+TEL;type=HOME;type=pref:555-555-5555
+TEL;type=WORK:555-555-5555
+TEL;type=WORK;type=FAX:555-555-5555
+item1.ADR;type=WORK;type=pref:;;1 Infinite Circle;Exampletino\, CA 99999;USA;;
+item1.X-ABADR:us
+NOTE:This is a contact created in Mulberry.
+item2.URL;type=pref:http://www.example.com/~magic
+item2.X-ABLabel:_$!<HomePage>!$_
+UID:782DAAF92CB1ED1BC155CDB3@D76FAF7B10D9E8D2D41F779D
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/3.vcf b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/put/3.vcf
new file mode 100644 (file)
index 0000000..37c3b81
--- /dev/null
@@ -0,0 +1,12 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Kawado;Saeko;;;
+FN:Snow Leopard
+ORG:Snow Leopard;
+EMAIL;type=INTERNET;type=WORK;type=pref:snowleopard_apple@example.com
+TEL;type=WORK;type=pref:555-555-5555
+item1.ADR;type=WORK;type=pref:;;2 Fidel Ave. Suite 1;Mountain Top;CA;99999;USA
+item1.X-ABADR:us
+X-ABShowAs:COMPANY
+UID:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1:ABPerson
+END:VCARD
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/sync/1.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/sync/1.xml
new file mode 100644 (file)
index 0000000..7f454b3
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:">
+<D:prop>
+<D:supported-report-set/>
+<D:sync-token/>
+</D:prop>
+</D:propfind>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/sync/2.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CardDAV/vreports/sync/2.xml
new file mode 100644 (file)
index 0000000..99ee3db
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:sync-collection xmlns:D="DAV:">
+<D:sync-token/>
+<D:prop/>
+</D:sync-collection>
diff --git a/apps/dav/tests/travis/caldavtest/serverinfo.dtd b/apps/dav/tests/travis/caldavtest/serverinfo.dtd
new file mode 100644 (file)
index 0000000..d642f4f
--- /dev/null
@@ -0,0 +1,43 @@
+<!--
+ Copyright (c) 2006-2015 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!ELEMENT serverinfo (host, path, nonsslport, sslport, unix?,
+                                               host2?, nonsslport2?, sslport2?, unix2?,
+                                               authtype?, waitcount?, waitdelay?, waitsuccess?,
+                                               features?, substitutions)? >
+
+       <!ELEMENT host                  (#PCDATA)>
+       <!ELEMENT path                  (#PCDATA)>
+       <!ELEMENT nonsslport    (#PCDATA)>
+       <!ELEMENT sslport               (#PCDATA)>
+       <!ELEMENT unix                  (#PCDATA)>
+       <!ELEMENT host2                 (#PCDATA)>
+       <!ELEMENT nonsslport2   (#PCDATA)>
+       <!ELEMENT sslport2              (#PCDATA)>
+       <!ELEMENT unix2                 (#PCDATA)>
+       <!ELEMENT authtype              (#PCDATA)>
+       <!ELEMENT waitdelay     (#PCDATA)>
+       <!ELEMENT waitcount     (#PCDATA)>
+       <!ELEMENT waitsuccess   (#PCDATA)>
+       <!ELEMENT features      (feature*)>
+               <!ELEMENT feature   (#PCDATA)>
+       <!ELEMENT substitutions (substitution|repeat)*>
+               <!ELEMENT repeat        (substitution+)>
+               <!ATTLIST repeat count CDATA "1">
+               <!ELEMENT substitution  (key, value)>
+                       <!ELEMENT key                   (#PCDATA)>
+                       <!ELEMENT value                 (#PCDATA)>
+       
diff --git a/apps/dav/tests/travis/caldavtest/serverinfo.xml b/apps/dav/tests/travis/caldavtest/serverinfo.xml
new file mode 100644 (file)
index 0000000..dea8f5a
--- /dev/null
@@ -0,0 +1,854 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE serverinfo SYSTEM
+               "/home/deepdiver/Development/ownCloud/master/apps/dav/tests/travis/caldavtest/serverinfo.dtd">
+
+<!--
+ Copyright (c) 2006-2015 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<serverinfo>
+       <host>localhost</host>
+       <nonsslport>8888</nonsslport>
+       <authtype>basic</authtype>
+       <!-- <unix>/tmp/caldavd_requests/unsecured.sock</unix> -->
+
+       <waitcount>120</waitcount>
+       <waitdelay>0.25</waitdelay>
+       <waitsuccess>30</waitsuccess>
+
+       <features>
+               <!--  Generic WebDAV extensions -->
+               <feature>COPY Method</feature>                                                  <!-- COPY method -->
+               <feature>MOVE Method</feature>                                                  <!-- MOVE method -->
+               <feature>Extended MKCOL</feature>                                               <!-- Extended MKCOL -->
+
+               <!-- ACL related -->
+               <feature>ACL Method</feature>                                                   <!-- ACL method -->
+               <feature>acl-principal-prop-set REPORT</feature>                <!-- ACL acl-principal-prop-set REPORT -->
+               <feature>principal-match REPORT</feature>                               <!-- ACL principal-match REPORT -->
+               <feature>principal-property-search REPORT</feature>             <!-- ACL principal-property-search REPORT -->
+               <feature>principal-search-property-set REPORT</feature> <!-- ACL principal-search-property-set REPORT -->
+               <feature>calendarserver-principal-search REPORT</feature>       <!-- ACL calendarserver-principal-search REPORT -->
+
+               <feature>add-member</feature>                                   <!-- Add-member used to create resources -->
+               <!-- <feature>auth-on-root</feature> -->                <!-- Whether the server requires authentication on the root URI -->
+               <feature>brief</feature>                                            <!-- Brief header for PROPFIND, REPORT -->
+               <feature>bulk-post</feature>                                    <!-- Bulk POST requests -->
+               <feature>ctag</feature>                                                 <!-- ctag extension -->
+               <feature>current-user-principal</feature>               <!-- current-user-principal extension -->
+               <feature>directory listing</feature>                    <!-- GET on collection -->
+               <feature>extended-principal-search</feature>    <!-- Extended principal-property-search REPORT extension -->
+               <feature>expand-property</feature>                              <!-- Expand property REPORT -->
+               <feature>only-proxy-groups</feature>                    <!-- Group-membership only includes delegated-to groups -->
+               <feature>limits</feature>                                               <!-- max-collections and max-resources limits -->
+               <feature>own-root</feature>                                             <!-- / is owned by this service -->
+               <feature>prefer</feature>                                               <!-- Prefer header overall support -->
+               <feature>prefer-minimal</feature>                               <!-- Prefer header return=minimal -->
+               <feature>prefer-representation</feature>                <!-- Prefer header return=representation -->
+               <feature>prefer-noroot</feature>                                <!-- Prefer header depth-noroot -->
+               <feature>quota</feature>                                                <!-- WebDAV QUOTA -->
+               <!-- <feature>quota-on-resources</feature> -->  <!-- WebDAV QUOTA on calendar and address book object resources -->
+               <feature>resource-id</feature>                                  <!-- WebDAV BIND DAV:resource-id property -->
+               <feature>sync-report</feature>                                  <!-- WebDAV collection sync REPORT -->
+               <!-- <feature>sync-report-limit</feature> -->   <!-- WebDAV collection sync REPORT DAV:limit support -->
+               <feature>sync-report-home</feature>                             <!-- WebDAV collection sync REPORT on Homes -->
+               <feature>sync-report-config-token</feature>             <!-- Sync REPORT token includes configuration component -->
+               <feature>well-known</feature>                                   <!-- well-known feature -->
+
+               <!-- <feature>per-object-ACLs</feature> -->             <!-- ACL for objects in calendar/address books -->
+               <!-- <feature>regular-collection</feature> -->  <!-- Regular collections allowed in calendar/address book homes -->
+
+               <feature>json-data</feature>                                    <!-- jCal and jCard support -->
+
+               <!--  CalendarServer specific extensions -->
+               <feature>control-api</feature>                                  <!-- Control API support -->
+
+               <!-- CalDAV specific extension -->
+               <feature>caldav</feature>                                           <!-- Basic CalDAV feature enabler -->
+               <feature>attachments-collection</feature>               <!-- Server uses a collection in same WebDAV tree to store attachments -->
+               <feature>auto-accept</feature>                                  <!-- Auto-accept for rooms & locations -->
+               <feature>auto-accept-modes</feature>                    <!-- Auto-accept modes -->
+               <feature>client-fix-TRANSP</feature>                    <!-- fix client TRANSP -->
+               <!-- <feature>dropbox</feature> -->                             <!-- dropbox extension -->
+               <feature>default-alarms</feature>                               <!-- default alarms extension -->
+               <feature>EMAIL parameter</feature>                              <!-- Server normalizes cuaddress and adds EMAIL parameter -->
+               <feature>extended-freebusy</feature>            <!-- Extended freebusy response -->
+               <feature>freebusy-url</feature>                         <!-- Freebusy URL -->
+               <feature>group-attendee-expansion</feature>         <!-- Auto-expansion of group attendees -->
+               <feature>implicit-scheduling</feature>                  <!-- CalDAV scheduling - implicit -->
+               <feature>location-resource-tracking</feature>   <!-- Server tracks who makes unscheduled changes to locations and resources -->
+               <feature>managed-attachments</feature>                  <!-- CalDAV Managed Attachments -->
+               <feature>maskuid</feature>                                              <!-- maskuid extension -->
+               <feature>no-duplicate-uids</feature>                    <!-- duplicate UIDs in same home not supported -->
+               <feature>partstat-timestamp</feature>                   <!-- Time stamps when PARTSTAT changes extension -->
+               <!-- <feature>podding</feature> -->                     <!-- Podded server -->
+               <feature>private-comments</feature>                             <!-- private-comments extension -->
+               <feature>private-events</feature>                               <!-- private-events extension -->
+               <feature>proxy</feature>                                                <!-- calendar-user-proxy extension -->
+               <!-- <feature>proxy-authz</feature> -->                 <!-- sudo user extension -->
+               <feature>recurrence-splitting</feature>                 <!-- Recurring components can be split -->
+               <feature>remove-duplicate-alarms</feature>      <!-- Server removes any duplicate alarms on PUT -->
+               <feature>query-extended</feature>                               <!-- calendar-query-extended extension -->
+               <feature>shared-calendars</feature>                             <!-- Shared calendars extension -->
+               <feature>share-calendars-to-groups</feature>    <!-- Share calendars to groups extension -->
+               <feature>schedule-changes</feature>                             <!-- schedule-changes property extension -->
+               <feature>split-calendars</feature>                              <!-- Calendars are split by component type -->
+               <feature>supported-component-sets</feature>             <!-- CALDAV:supported-calendar-component-sets on calendar homes -->
+               <feature>supported-component-sets-one</feature> <!-- Only single component calendars allowed to be created -->
+               <feature>timerange-low-limit</feature>                  <!-- Time-range only valid one year back -->
+               <feature>timerange-high-limit</feature>                 <!-- Time-range only valid 5 years ahead -->
+               <feature>timezones-by-reference</feature>               <!-- Timezones by reference enabled -->
+               <feature>timezone-service</feature>                             <!-- Timezone service extension for Wiki -->
+               <feature>timezone-std-service</feature>                 <!-- Timezone standard service extension -->
+               <!-- <feature>trash-collection</feature> -->                    <!-- Trash collection enabled -->
+               <feature>travel-time-busy</feature>                     <!-- Travel time appears as busy -->
+               <feature>vavailability</feature>                                <!-- VAVAILABILITY on inbox -->
+               <!-- <feature>vpoll</feature> -->                               <!-- VPOLL support for store and scheduling -->
+               <feature>webcal</feature>                                               <!-- Internet calendar subscription via GET on calendar collection -->
+
+               <!-- CardDAV specific extension -->
+               <feature>carddav</feature>                                              <!-- Basic CardDAV feature enabler -->
+               <feature>default-addressbook</feature>                  <!-- Default address book behavior -->
+               <feature>shared-addressbooks</feature>                  <!-- Shared address books extension -->
+               <feature>shared-addressbook-groups</feature>    <!-- Shared address book groups extension -->
+               <feature>directory-gateway</feature>                    <!-- Directory gateway extension -->
+
+       </features>
+
+       <substitutions>
+               <!-- Useful xpath shortcuts for verifiers -->
+               <substitution>
+                       <key>$multistatus-response-prefix:</key>
+                       <value>/{DAV:}multistatus/{DAV:}response</value>
+               </substitution>
+               <substitution>
+                       <key>$multistatus-href-prefix:</key>
+                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}href</value>
+               </substitution>
+               <substitution>
+                       <key>$verify-response-prefix:</key>
+                       <value>{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
+               </substitution>
+               <substitution>
+                       <key>$verify-property-prefix:</key>
+                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}propstat/{DAV:}prop</value>
+               </substitution>
+               <substitution>
+                       <key>$verify-bad-response:</key>
+                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}status</value>
+               </substitution>
+               <substitution>
+                       <key>$verify-error-response:</key>
+                       <value>/{DAV:}multistatus/{DAV:}response/{DAV:}error</value>
+               </substitution>
+               <substitution>
+                       <key>$CALDAV:</key>
+                       <value>urn:ietf:params:xml:ns:caldav</value>
+               </substitution>
+               <substitution>
+                       <key>$CARDDAV:</key>
+                       <value>urn:ietf:params:xml:ns:carddav</value>
+               </substitution>
+               <substitution>
+                       <key>$CS:</key>
+                       <value>http://calendarserver.org/ns/</value>
+               </substitution>
+
+               <!-- Server configuration settings -->
+               <!-- $host: and $hostssl: are implicitly added by CalDAVTester based
+                    on the host/nonsslport/sslport values and ssl command line switch -->
+
+               <!-- relative path to caldav root-->
+               <substitution>
+                       <key>$root:</key>
+                       <value>/remote.php/dav/</value>
+               </substitution>
+
+               <!-- relative path to main principal collection-->
+               <substitution>
+                       <key>$principalcollection:</key>
+                       <value>$root:principals/users/</value>
+               </substitution>
+
+               <!-- the core recored type collections-->
+               <substitution>
+                       <key>$uidstype:</key>
+                       <value>__uids__</value>
+               </substitution>
+               <substitution>
+                       <key>$userstype:</key>
+                       <value>users</value>
+               </substitution>
+               <substitution>
+                       <key>$groupstype:</key>
+                       <value>groups</value>
+               </substitution>
+               <substitution>
+                       <key>$locationstype:</key>
+                       <value>locations</value>
+               </substitution>
+               <substitution>
+                       <key>$resourcestype:</key>
+                       <value>resources</value>
+               </substitution>
+
+               <!-- relative path to record type principal collections-->
+               <substitution>
+                       <key>$principals_uids:</key>
+                       <value>$principalcollection:$uidstype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$principals_users:</key>
+                       <value>$principalcollection:$userstype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$principals_groups:</key>
+                       <value>$principalcollection:$groupstype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$principals_resources:</key>
+                       <value>$principalcollection:$resourcestype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$principals_locations:</key>
+                       <value>$principalcollection:$locationstype:/</value>
+               </substitution>
+
+               <!-- relative path to calendars collection-->
+               <substitution>
+                       <key>$calendars:</key>
+                       <value>$root:calendars/</value>
+               </substitution>
+
+               <!-- relative path to record type calendar collections-->
+               <substitution>
+                       <key>$calendars_uids:</key>
+                       <value>$calendars:$uidstype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$calendars_users:</key>
+                       <value>$calendars:$userstype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$calendars_resources:</key>
+                       <value>$calendars:$resourcestype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$calendars_locations:</key>
+                       <value>$calendars:$locationstype:/</value>
+               </substitution>
+
+               <!-- primary calendar name-->
+               <substitution>
+                       <key>$calendar:</key>
+                       <value>calendar</value>
+               </substitution>
+
+               <!-- primary tasks-only calendar name-->
+               <substitution>
+                       <key>$tasks:</key>
+                       <value>tasks</value>
+               </substitution>
+
+               <!-- primary polls-only calendar name-->
+               <substitution>
+                       <key>$polls:</key>
+                       <value>polls</value>
+               </substitution>
+
+               <!-- inbox name-->
+               <substitution>
+                       <key>$inbox:</key>
+                       <value>inbox</value>
+               </substitution>
+
+               <!-- outbox name-->
+               <substitution>
+                       <key>$outbox:</key>
+                       <value>outbox</value>
+               </substitution>
+
+               <!-- dropbox name-->
+               <substitution>
+                       <key>$dropbox:</key>
+                       <value>dropbox</value>
+               </substitution>
+
+               <!-- attachments name-->
+               <substitution>
+                       <key>$attachments:</key>
+                       <value>dropbox</value>
+               </substitution>
+
+               <!-- notification name-->
+               <substitution>
+                       <key>$notification:</key>
+                       <value>notification</value>
+               </substitution>
+
+               <!-- freebusy name-->
+               <substitution>
+                       <key>$freebusy:</key>
+                       <value>freebusy</value>
+               </substitution>
+
+               <!-- Sync home collection items - use "-" to include the home resource-->
+               <substitution>
+                       <key>$calendar_home_items_initial_sync:</key>
+                       <value>[-,$calendar:/,$tasks:/,$inbox:/,$outbox:/,$freebusy:,$notification:/]</value>
+               </substitution>
+
+               <!-- Sync collection extra items - use "-" to include the collection-->
+               <substitution>
+                       <key>$calendar_sync_extra_items:</key>
+                       <value>[-]</value>
+               </substitution>
+
+               <!-- Sync collection extra count - gets added to the totalcount value-->
+               <substitution>
+                       <key>$calendar_sync_extra_count:</key>
+                       <value>1</value> <!-- the request-uri resource is returned when no token passed-->
+               </substitution>
+
+               <!-- server-to-server inbox-->
+               <substitution>
+                       <key>$servertoserver:</key>
+                       <value>$root:inbox</value>
+               </substitution>
+
+               <!-- timezone service-->
+               <substitution>
+                       <key>$timezoneservice:</key>
+                       <value>$root:timezones</value>
+               </substitution>
+
+               <!-- timezone std service-->
+               <substitution>
+                       <key>$timezonestdservice:</key>
+                       <value>$root:stdtimezones</value>
+               </substitution>
+
+               <!-- relative path to addressbooks collection-->
+               <substitution>
+                       <key>$addressbooks:</key>
+                       <value>$root:addressbooks/</value>
+               </substitution>
+
+               <!-- relative path to record type addressbook collections-->
+               <substitution>
+                       <key>$addressbooks_uids:</key>
+                       <value>$addressbooks:$uidstype:/</value>
+               </substitution>
+               <substitution>
+                       <key>$addressbooks_users:</key>
+                       <value>$addressbooks:$userstype:/</value>
+               </substitution>
+
+               <!-- primary addressbook name -->
+               <substitution>
+                       <key>$addressbook:</key>
+                       <value>addressbook</value>
+               </substitution>
+
+               <!-- directory name -->
+               <substitution>
+                       <key>$directory:</key>
+                       <value>$root:directory/</value>
+               </substitution>
+
+               <!-- POST add-member URI suffix -->
+               <substitution>
+                       <key>$add-member:</key>
+                       <value>;add-member</value>
+               </substitution>
+
+               <!-- user id for admin user -->
+               <substitution>
+                       <key>$useradmin:</key>
+                       <value>admin</value>
+               </substitution>
+               <!-- guid for admin user -->
+               <substitution>
+                       <key>$useradminguid:</key>
+                       <value>0C8BDE62-E600-4696-83D3-8B5ECABDFD2E</value>
+               </substitution>
+               <!-- password for admin user -->
+               <substitution>
+                       <key>$pswdadmin:</key>
+                       <value>admin</value>
+               </substitution>
+
+               <!-- relative path to admin principal resource-->
+               <substitution>
+                       <key>$principal_admin:</key>
+                       <value>$principals_users:$useradmin:/</value>
+               </substitution>
+               <substitution>
+                       <key>$principaluri_admin:</key>
+                       <value>$principals_uids:$useradminguid:/</value>
+               </substitution>
+
+               <!-- user id for apprentice user -->
+               <substitution>
+                       <key>$userapprentice:</key>
+                       <value>apprentice</value>
+               </substitution>
+               <!-- guid for apprentice user -->
+               <substitution>
+                       <key>$userapprenticeguid:</key>
+                       <value>29B6C503-11DF-43EC-8CCA-40C7003149CE</value>
+               </substitution>
+               <!-- password for admin user -->
+               <substitution>
+                       <key>$pswdapprentice:</key>
+                       <value>apprentice</value>
+               </substitution>
+
+               <!-- relative path to apprentice principal resource-->
+               <substitution>
+                       <key>$principal_apprentice:</key>
+                       <value>$principals_users:$userapprentice:/</value>
+               </substitution>
+               <substitution>
+                       <key>$principaluri_apprentice:</key>
+                       <value>$principals_uids:$userapprenticeguid:/</value>
+               </substitution>
+
+               <!-- user id for proxy user -->
+               <substitution>
+                       <key>$userproxy:</key>
+                       <value>superuser</value>
+               </substitution>
+               <!-- password for proxy user -->
+               <substitution>
+                       <key>$pswdproxy:</key>
+                       <value>superuser</value>
+               </substitution>
+
+               <!--  Forty user accounts -->
+               <repeat count="40">
+                       <!-- user id -->
+                       <substitution>
+                               <key>$userid%d:</key>
+                               <value>user%02d</value>
+                       </substitution>
+                       <!-- user guid -->
+                       <substitution>
+                               <key>$userguid%d:</key>
+                               <value>10000000-0000-0000-0000-000000000%03d</value>
+                       </substitution>
+                       <!-- user name -->
+                       <substitution>
+                               <key>$username%d:</key>
+                               <value>User %02d</value>
+                       </substitution>
+                       <!-- user name URI encoded -->
+                       <substitution>
+                               <key>$username-encoded%d:</key>
+                               <value>User%%20%02d</value>
+                       </substitution>
+                       <!-- first name -->
+                       <substitution>
+                               <key>$firstname%d:</key>
+                               <value>User</value>
+                       </substitution>
+                       <!-- last name -->
+                       <substitution>
+                               <key>$lastname%d:</key>
+                               <value>%02d</value>
+                       </substitution>
+                       <!-- password -->
+                       <substitution>
+                               <key>$pswd%d:</key>
+                               <value>user%02d</value>
+                       </substitution>
+                       <!-- relative path to user principal resource-->
+                       <substitution>
+                               <key>$principal%d:</key>
+                               <value>$principals_users:$userid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$principaluri%d:</key>
+                               <value>$principalcollection:$userid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$principal%dnoslash:</key>
+                               <value>$principals_users:$userid%d:</value>
+                       </substitution>
+
+                       <!-- relative path to user calendar home-->
+                       <substitution>
+                               <key>$calendarhome%d:</key>
+                               <value>$calendars_uids:$userguid%d:</value>
+                       </substitution>
+                       <!-- relative path to user alternate calendar home-->
+                       <substitution>
+                               <key>$calendarhomealt%d:</key>
+                               <value>$calendars_users:$userid%d:</value>
+                       </substitution>
+                       <!-- relative path to user calendar-->
+                       <substitution>
+                               <key>$calendarpath%d:</key>
+                               <value>$calendarhome%d:/$calendar:</value>
+                       </substitution>
+                       <!-- relative path to user alternate calendar-->
+                       <substitution>
+                               <key>$calendarpathalt%d:</key>
+                               <value>$calendarhomealt%d:/$calendar:</value>
+                       </substitution>
+                       <!-- relative path to user tasks calendar-->
+                       <substitution>
+                               <key>$taskspath%d:</key>
+                               <value>$calendarhome%d:/$tasks:</value>
+                       </substitution>
+                       <!-- relative path to user polls calendar-->
+                       <substitution>
+                               <key>$pollspath%d:</key>
+                               <value>$calendarhome%d:/$polls:</value>
+                       </substitution>
+                       <!-- relative path to user inbox-->
+                       <substitution>
+                               <key>$inboxpath%d:</key>
+                               <value>$calendarhome%d:/$inbox:</value>
+                       </substitution>
+                       <!-- relative path to user outbox-->
+                       <substitution>
+                               <key>$outboxpath%d:</key>
+                               <value>$calendarhome%d:/$outbox:</value>
+                       </substitution>
+                       <!-- relative path to user dropbox-->
+                       <substitution>
+                               <key>$dropboxpath%d:</key>
+                               <value>$calendarhome%d:/$dropbox:</value>
+                       </substitution>
+                       <!-- relative path to user notification-->
+                       <substitution>
+                               <key>$notificationpath%d:</key>
+                               <value>$calendarhome%d:/$notification:</value>
+                       </substitution>
+                       <!-- relative path to user freebusy-->
+                       <substitution>
+                               <key>$freebusypath%d:</key>
+                               <value>$calendarhome%d:/$freebusy:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$email%d:</key>
+                               <value>$userid%d:@example.com</value>
+                       </substitution>
+                       <!-- calendar user address of user-->
+                       <substitution>
+                               <key>$cuaddr%d:</key>
+                               <value>mailto:$email%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$cuaddralt%d:</key>
+                               <value>$cuaddr%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$cuaddraltnoslash%d:</key>
+                               <value>$cuaddr%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$cuaddrurn%d:</key>
+                               <value>urn:x-uid:$userguid%d:</value>
+                       </substitution>
+
+                       <!-- relative path to user addressbook home-->
+                       <substitution>
+                               <key>$addressbookhome%d:</key>
+                               <value>$addressbooks:users/$userid%d:</value>
+                       </substitution>
+                       <!-- relative path to user addressbook-->
+                       <substitution>
+                               <key>$addressbookpath%d:</key>
+                               <value>$addressbookhome%d:/$addressbook:</value>
+                       </substitution>
+               </repeat>
+
+               <!--  Ten public accounts -->
+               <repeat count="10">
+                       <!-- user id -->
+                       <substitution>
+                               <key>$publicuserid%d:</key>
+                               <value>public%02d</value>
+                       </substitution>
+                       <!-- user guid -->
+                       <substitution>
+                               <key>$publicuserguid%d:</key>
+                               <value>50000000-0000-0000-0000-0000000000%02d</value>
+                       </substitution>
+                       <!-- user name -->
+                       <substitution>
+                               <key>$publicusername%d:</key>
+                               <value>Public %02d</value>
+                       </substitution>
+                       <!-- password -->
+                       <substitution>
+                               <key>$publicpswd%d:</key>
+                               <value>public%02d</value>
+                       </substitution>
+                       <!-- relative path to user principal resource-->
+                       <substitution>
+                               <key>$publicprincipal%d:</key>
+                               <value>$principals_users:$publicuserid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$publicprincipaluri%d:</key>
+                               <value>$principals_uids:$publicuserguid%d:/</value>
+                       </substitution>
+                       <!-- relative path to user calendar home-->
+                       <substitution>
+                               <key>$publiccalendarhome%d:</key>
+                               <value>$calendars_uids:$publicuserguid%d:</value>
+                       </substitution>
+                       <!-- relative path to user calendar-->
+                       <substitution>
+                               <key>$publiccalendarpath%d:</key>
+                               <value>$calendars_uids:$publicuserguid%d:/$calendar:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$publicemail%d:</key>
+                               <value>$publicuserid%d:@example.com</value>
+                       </substitution>
+                       <!-- calendar user address of user-->
+                       <substitution>
+                               <key>$publiccuaddr%d:</key>
+                               <value>mailto:$publicemail%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$publiccuaddralt%d:</key>
+                               <value>$publiccuaddr%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$publiccuaddrurn%d:</key>
+                               <value>urn:x-uid:$publicuserguid%d:</value>
+                       </substitution>
+               </repeat>
+
+               <!--  Twenty resource accounts -->
+               <repeat count="20">
+                       <substitution>
+                               <key>$resourceid%d:</key>
+                               <value>resource%02d</value>
+                       </substitution>
+                       <!-- resource guid-->
+                       <substitution>
+                               <key>$resourceguid%d:</key>
+                               <value>40000000-0000-0000-0000-000000000%03d</value>
+                       </substitution>
+                       <!-- resource name-->
+                       <substitution>
+                               <key>$resourcename%d:</key>
+                               <value>Resource %02d</value>
+                       </substitution>
+                       <!-- relative path to first resource calendar home-->
+                       <substitution>
+                               <key>$rcalendarhome%d:</key>
+                               <value>$calendars_uids:$resourceguid%d:</value>
+                       </substitution>
+                       <!-- relative path to first resource calendar home-->
+                       <substitution>
+                               <key>$rcalendarpath%d:</key>
+                               <value>$calendars_uids:$resourceguid%d:/$calendar:</value>
+                       </substitution>
+                       <!-- relative path to first resource inbox-->
+                       <substitution>
+                               <key>$rinboxpath%d:</key>
+                               <value>$calendars_uids:$resourceguid%d:/$inbox:</value>
+                       </substitution>
+                       <!-- relative path to first resource outbox-->
+                       <substitution>
+                               <key>$routboxpath%d:</key>
+                               <value>$calendars_uids:$resourceguid%d:/$outbox:</value>
+                       </substitution>
+                       <!-- relative path to first resource principal resource-->
+                       <substitution>
+                               <key>$rprincipal%d:</key>
+                               <value>$principals_resources:$resourceid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$rprincipaluri%d:</key>
+                               <value>$principals_uids:$resourceguid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$rcuaddralt%d:</key>
+                               <value>$rcuaddrurn%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$rcuaddrurn%d:</key>
+                               <value>urn:x-uid:$resourceguid%d:</value>
+                       </substitution>
+               </repeat>
+
+               <!--  Ten Location accounts -->
+               <repeat count="10">
+                       <substitution>
+                               <key>$locationid%d:</key>
+                               <value>location%02d</value>
+                       </substitution>
+                       <!-- location guid-->
+                       <substitution>
+                               <key>$locationguid%d:</key>
+                               <value>30000000-0000-0000-0000-000000000%03d</value>
+                       </substitution>
+                       <!-- location name-->
+                       <substitution>
+                               <key>$locationname%d:</key>
+                               <value>Location %02d</value>
+                       </substitution>
+                       <!-- relative path to first location calendar home-->
+                       <substitution>
+                               <key>$lcalendarhome%d:</key>
+                               <value>$calendars_uids:$locationguid%d:</value>
+                       </substitution>
+                       <!-- relative path to first location calendar home-->
+                       <substitution>
+                               <key>$lcalendarpath%d:</key>
+                               <value>$calendars_uids:$locationguid%d:/$calendar:</value>
+                       </substitution>
+                       <!-- relative path to first location inbox-->
+                       <substitution>
+                               <key>$linboxpath%d:</key>
+                               <value>$calendars_uids:$locationguid%d:/$inbox:</value>
+                       </substitution>
+                       <!-- relative path to first location outbox-->
+                       <substitution>
+                               <key>$loutboxpath%d:</key>
+                               <value>$calendars_uids:$locationguid%d:/$outbox:</value>
+                       </substitution>
+                       <!-- relative path to first location principal resource-->
+                       <substitution>
+                               <key>$lprincipal%d:</key>
+                               <value>$principals_resources:$locationid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$lprincipaluri%d:</key>
+                               <value>$principals_uids:$locationguid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$lcuaddralt%d:</key>
+                               <value>$lprincipaluri%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$lcuaddrurn%d:</key>
+                               <value>urn:x-uid:$locationguid%d:</value>
+                       </substitution>
+               </repeat>
+
+
+               <!--  Ten Group accounts -->
+               <repeat count="40">
+                       <substitution>
+                               <key>$groupid%d:</key>
+                               <value>group%02d</value>
+                       </substitution>
+                       <!-- group guid-->
+                       <substitution>
+                               <key>$groupguid%d:</key>
+                               <value>20000000-0000-0000-0000-000000000%03d</value>
+                       </substitution>
+                       <!-- group name-->
+                       <substitution>
+                               <key>$groupname%d:</key>
+                               <value>Group %02d</value>
+                       </substitution>
+                       <!-- relative path to first group principal resource-->
+                       <substitution>
+                               <key>$gprincipal%d:</key>
+                               <value>$principals_resources:$groupid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$gprincipaluri%d:</key>
+                               <value>$principals_uids:$groupguid%d:/</value>
+                       </substitution>
+                       <substitution>
+                               <key>$gemail%d:</key>
+                               <value>$groupid%d:@example.com</value>
+                       </substitution>
+                       <substitution>
+                               <key>$gcuaddralt%d:</key>
+                               <value>$gprincipaluri%d:</value>
+                       </substitution>
+                       <substitution>
+                               <key>$gcuaddrurn%d:</key>
+                               <value>urn:x-uid:$groupguid%d:</value>
+                       </substitution>
+               </repeat>
+
+               <!--  User with non-ascii name -->
+               <substitution>
+                       <key>$i18nid:</key>
+                       <value>i18nuser</value>
+               </substitution>
+               <!-- group guid-->
+               <substitution>
+                       <key>$i18nguid:</key>
+                       <value>860B3EE9-6D7C-4296-9639-E6B998074A78</value>
+               </substitution>
+               <!-- group name-->
+               <substitution>
+                       <key>$i18nname:</key>
+                       <value>まだ</value>
+               </substitution>
+               <!-- password -->
+               <substitution>
+                       <key>$i18npswd:</key>
+                       <value>i18nuser</value>
+               </substitution>
+               <!-- relative path to user calendar-->
+               <substitution>
+                       <key>$i18ncalendarpath:</key>
+                       <value>$calendars_uids:$i18nguid:/$calendar:</value>
+               </substitution>
+               <substitution>
+                       <key>$i18nemail:</key>
+                       <value>$i18nid:@example.com</value>
+               </substitution>
+               <!-- CUAddrs -->
+               <substitution>
+                       <key>$i18ncuaddr:</key>
+                       <value>mailto:$i18nemail:</value>
+               </substitution>
+               <substitution>
+                       <key>$i18ncuaddrurn:</key>
+                       <value>urn:x-uid:$i18nguid:</value>
+               </substitution>
+
+               <!-- relative path to disabled group principal resource-->
+               <substitution>
+                       <key>$principaldisabled:</key>
+                       <value>$principals_groups:disabledgroup/</value>
+               </substitution>
+               <substitution>
+                       <key>$principaluridisabled:</key>
+                       <value>$principals_uids:disabledgroup/</value>
+               </substitution>
+               <!-- calendar user address of disabled group-->
+               <substitution>
+                       <key>$cuaddrdisabled:</key>
+                       <value>$principals_uids:disabledgroup/</value>
+               </substitution>
+
+               <!--  Override some of the above definitions for special cases -->
+
+               <!-- calendar user address of second user-->
+               <substitution>
+                       <key>$cuaddr2:</key>
+                       <value>MAILTO:$email2:</value>
+               </substitution>
+
+       </substitutions>
+</serverinfo>
diff --git a/apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml b/apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml
new file mode 100644 (file)
index 0000000..046c3d5
--- /dev/null
@@ -0,0 +1,246 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<caldavtest>
+       <description>Test addressbook sharing</description>
+
+       <require-feature>
+               <feature>carddav</feature>
+       </require-feature>
+
+       <start>
+       </start>
+       
+       <test-suite name='Read-write addressbook'>
+               <test name='1'>
+                       <description>POST invitation</description>
+                       <request>
+                               <method>POST</method>
+                               <ruri>$addressbookpath1:</ruri>
+                               <data>
+                                       <content-type>text/xml; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/1.xml</filepath>
+                               </data>
+                               <verify>
+                                       <callback>statusCode</callback>
+                               </verify>
+                       </request>
+               </test>
+               <test name='4'>
+                       <description>Shared addressbook exists</description>
+                       <request user="$userid2:" pswd="$pswd2:">
+                               <method>PROPFIND</method>
+                               <ruri>$addressbookpath1:/</ruri>
+                               <header>
+                                       <name>Depth</name>
+                                       <value>0</value>
+                               </header>
+                               <data>
+                                       <content-type>text/xml; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/4.xml</filepath>
+                               </data>
+                               <verify>
+                                       <callback>xmlElementMatch</callback>
+                                       <arg>
+                                               <name>exists</name>
+                                               <value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+                                               <value>$verify-property-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+                                               <value>$verify-property-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:carddav}addressbook</value>
+                                               <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+                                               <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+                                               <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+                                               <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+                                       </arg>
+                                       <arg>
+                                               <name>notexists</name>
+                                               <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+                                               <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='4a'>
+                       <description>Shared calendar exists Depth:1</description>
+                       <request user="$userid2:" pswd="$pswd2:">
+                               <method>PROPFIND</method>
+                               <ruri>$addressbookhome2:/</ruri>
+                               <header>
+                                       <name>Depth</name>
+                                       <value>1</value>
+                               </header>
+                               <data>
+                                       <content-type>text/xml; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/4.xml</filepath>
+                               </data>
+                               <verify>
+                                       <callback>xmlElementMatch</callback>
+                                       <arg>
+                                               <name>parent</name>
+                                               <value>$multistatus-response-prefix:[^{DAV:}href=$addressbookhome2:/ade1a55d408167e8ff77611c0eebe8f80579b549/]</value>
+                                       </arg>
+                                       <arg>
+                                               <name>exists</name>
+                                               <!--<value>$verify-response-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>-->
+                                               <value>$verify-response-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+                                               <value>$verify-response-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:carddav}addressbook</value>
+                                               <value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+                                               <value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+                                               <value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+                                               <value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+                                       </arg>
+                                       <arg>
+                                               <name>notexists</name>
+                                               <value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+                                               <value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='5'>
+                       <description>Original calendar unchanged</description>
+                       <request>
+                               <method>PROPFIND</method>
+                               <ruri>$addressbookpath1:</ruri>
+                               <header>
+                                       <name>Depth</name>
+                                       <value>0</value>
+                               </header>
+                               <data>
+                                       <content-type>text/xml; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/4.xml</filepath>
+                               </data>
+                               <verify>
+                                       <callback>xmlElementMatch</callback>
+                                       <arg>
+                                               <name>exists</name>
+                                               <value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='6'>
+                       <description>Sharee creates contact</description>
+                       <request user="$userid2:" pswd="$pswd2:">
+                               <method>PUT</method>
+                               <ruri>$addressbookpath1:/1.vcf</ruri>
+                               <data>
+                                       <content-type>text/vcard; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/6.vcf</filepath>
+                               </data>
+                               <verify>
+                                       <callback>statusCode</callback>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='7'>
+                       <description>Sharer sees contact</description>
+                       <request>
+                               <method>GET</method>
+                               <ruri>$addressbookpath1:/1.vcf</ruri>
+                               <verify>
+                                       <callback>addressDataMatch</callback>
+                                       <arg>
+                                               <name>filepath</name>
+                                               <value>Resource/CardDAV/sharing/read-write/6.vcf</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='8'>
+                       <description>Sharer changes contact</description>
+                       <request>
+                               <method>PUT</method>
+                               <ruri>$addressbookpath1:/1.vcf</ruri>
+                               <data>
+                                       <content-type>text/vcard; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/7.vcf</filepath>
+                               </data>
+                               <verify>
+                                       <callback>statusCode</callback>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='9'>
+                       <description>Sharee sees changed contact</description>
+                       <request user="$userid2:" pswd="$pswd2:">
+                               <method>GET</method>
+                               <ruri>$addressbookpath1:/1.vcf</ruri>
+                               <verify>
+                                       <callback>addressDataMatch</callback>
+                                       <arg>
+                                               <name>filepath</name>
+                                               <value>Resource/CardDAV/sharing/read-write/7.vcf</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+
+               <test name='10'>
+                       <description>Sharer creates event</description>
+                       <request>
+                               <method>PUT</method>
+                               <ruri>$addressbookpath1:/2.vcf</ruri>
+                               <data>
+                                       <content-type>text/vcard; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/8.vcf</filepath>
+                               </data>
+                               <verify>
+                                       <callback>statusCode</callback>
+                               </verify>
+                       </request>
+               </test>
+               <test name='11'>
+                       <description>Sharee sees new event</description>
+                       <request user="$userid2:" pswd="$pswd2:">
+                               <method>GET</method>
+                               <ruri>$addressbookpath1:/2.vcf</ruri>
+                               <verify>
+                                       <callback>addressDataMatch</callback>
+                                       <arg>
+                                               <name>filepath</name>
+                                               <value>Resource/CardDAV/sharing/read-write/8.vcf</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+               <test name='12'>
+                       <description>Sharee changes event</description>
+                       <request user="$userid2:" pswd="$pswd2:">
+                               <method>PUT</method>
+                               <ruri>$addressbookpath1:/2.vcf</ruri>
+                               <data>
+                                       <content-type>text/vcard; charset=utf-8</content-type>
+                                       <filepath>Resource/CardDAV/sharing/read-write/9.vcf</filepath>
+                               </data>
+                               <verify>
+                                       <callback>statusCode</callback>
+                               </verify>
+                       </request>
+               </test>
+               <test name='13'>
+                       <description>Sharer sees changed event</description>
+                       <request>
+                               <method>GET</method>
+                               <ruri>$addressbookpath1:/2.vcf</ruri>
+                               <verify>
+                                       <callback>addressDataMatch</callback>
+                                       <arg>
+                                               <name>filepath</name>
+                                               <value>Resource/CardDAV/sharing/read-write/9.vcf</value>
+                                       </arg>
+                               </verify>
+                       </request>
+               </test>
+       </test-suite>
+       
+       <end>
+       </end>
+
+</caldavtest>
index 46a6a98e273bd5104f2c809c043a9f74003bb58a..a8bd9f11b38dfee5a4dcc41066605ffc47d5d42c 100644 (file)
@@ -9,9 +9,12 @@ sleep 30
 
 # run the tests
 cd "$SCRIPTPATH/CalDAVTester"
-PYTHONPATH="$SCRIPTPATH/pycalendar/src" python testcaldav.py --print-details-onfail -s "$SCRIPTPATH/../caldavtest/config/serverinfo.xml" -o cdt.txt \
-       "$SCRIPTPATH/../caldavtest/tests/CardDAV/current-user-principal.xml" \
-       "$SCRIPTPATH/../caldavtest/tests/CardDAV/sync-report.xml"
+PYTHONPATH="$SCRIPTPATH/pycalendar/src" python testcaldav.py --print-details-onfail --basedir "$SCRIPTPATH/../caldavtest/" -o cdt.txt \
+       "CardDAV/current-user-principal.xml" \
+       "CardDAV/sync-report.xml" \
+       "CardDAV/sharing-addressbooks.xml"
+
+
 RESULT=$?
 
 tail "$/../../../../../data-autotest/owncloud.log"