[Pkg-owncloud-commits] [php-sabredav] 08/148: Migrated MKCOL and MKCALENDAR to the new system.

David Prévot taffit at moszumanska.debian.org
Wed Apr 15 01:37:00 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository php-sabredav.

commit 9caf8ebebd2615ec55f88271c381629a1b49e085
Author: Evert Pot <evert at rooftopsolutions.nl>
Date:   Wed Dec 17 01:12:24 2014 -0500

    Migrated MKCOL and MKCALENDAR to the new system.
---
 composer.json                                      |   2 +-
 lib/CalDAV/Plugin.php                              |  21 +-
 lib/CalDAV/Subscriptions/Plugin.php                |   3 +
 lib/CalDAV/Subscriptions/Subscription.php          |   2 +-
 lib/CalDAV/Xml/CalendarData.php                    | 117 ++++++++
 lib/CalDAV/Xml/Filter/CompFilter.php               | 124 ++++++++
 .../Xml/Filter/ParamFilter.php}                    |  60 ++--
 lib/CalDAV/Xml/Filter/PropFilter.php               | 128 ++++++++
 lib/CalDAV/Xml/Notification/Invite.php             | 334 +++++++++++++++++++++
 lib/CalDAV/Xml/Notification/InviteReply.php        | 237 +++++++++++++++
 .../Xml/Notification/NotificationInterface.php     |  46 +++
 lib/CalDAV/Xml/Notification/SystemStatus.php       | 212 +++++++++++++
 .../Xml/Property/AllowedSharingModes.php}          |  65 ++--
 lib/CalDAV/Xml/Property/Invite.php                 | 250 +++++++++++++++
 lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php | 137 +++++++++
 .../Property/SupportedCalendarComponentSet.php}    |  70 +++--
 .../Xml/Property/SupportedCalendarData.php}        |  47 ++-
 .../Xml/Property/SupportedCollationSet.php}        |  48 ++-
 .../Xml/Request/CalendarMultiGetReport.php}        |  69 ++++-
 lib/CalDAV/Xml/Request/CalendarQueryReport.php     | 141 +++++++++
 lib/CalDAV/Xml/Request/InviteReply.php             | 175 +++++++++++
 .../Xml/Request/MkCalendar.php}                    |  31 +-
 lib/CalDAV/Xml/Request/Share.php                   | 135 +++++++++
 lib/DAV/Browser/Plugin.php                         |   2 +-
 lib/DAV/CorePlugin.php                             |  15 +-
 lib/DAV/Property/ResourceType.php                  | 124 --------
 lib/DAV/Property/SupportedMethodSet.php            |  68 -----
 lib/DAV/XMLUtil.php                                |   7 +
 lib/DAV/Xml/Property/ResourceType.php              |  20 +-
 lib/DAV/Xml/Property/SupportedLock.php             |   8 +-
 lib/DAV/Xml/Request/MkCol.php                      |  24 +-
 lib/DAV/Xml/Response/MultiStatus.php               |  16 +-
 tests/Sabre/CalDAV/PluginTest.php                  |   2 +-
 tests/Sabre/CalDAV/SharingPluginTest.php           |   6 +-
 tests/Sabre/DAV/Property/ResourceTypeTest.php      | 105 -------
 tests/Sabre/DAV/ServerMKCOLTest.php                |   2 +-
 36 files changed, 2349 insertions(+), 504 deletions(-)

diff --git a/composer.json b/composer.json
index da9888b..afcf1de 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,7 @@
         "sabre/vobject": "~3.3.4",
         "sabre/event" : "~2.0.0",
         "sabre/http" : "~3.0.4",
-        "sabre/xml"  : "~0.2.0",
+        "sabre/xml"  : "~0.2.1",
         "ext-dom": "*",
         "ext-pcre": "*",
         "ext-spl": "*",
diff --git a/lib/CalDAV/Plugin.php b/lib/CalDAV/Plugin.php
index 35dec65..c3f02a8 100644
--- a/lib/CalDAV/Plugin.php
+++ b/lib/CalDAV/Plugin.php
@@ -182,6 +182,9 @@ class Plugin extends DAV\ServerPlugin {
         $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre\\CalDAV\\Property\\SupportedCalendarComponentSet';
         $server->propertyMap['{' . self::NS_CALDAV . '}schedule-calendar-transp'] = 'Sabre\\CalDAV\\Property\\ScheduleCalendarTransp';
 
+        $server->xml->elementMap['{' . self::NS_CALDAV . '}mkcalendar'] = 'Sabre\\CalDAV\\Xml\\Request\\MkCalendar';
+        $server->xml->elementMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre\\CalDAV\\Xml\\Property\\SupportedCalendarComponentSet';
+
         $server->resourceTypeMapping['\\Sabre\\CalDAV\\ICalendar'] = '{urn:ietf:params:xml:ns:caldav}calendar';
 
         $server->resourceTypeMapping['\\Sabre\\CalDAV\\Principal\\IProxyRead'] = '{http://calendarserver.org/ns/}calendar-proxy-read';
@@ -250,13 +253,6 @@ class Plugin extends DAV\ServerPlugin {
      */
     function httpMkCalendar(RequestInterface $request, ResponseInterface $response) {
 
-        // Due to unforgivable bugs in iCal, we're completely disabling MKCALENDAR support
-        // for clients matching iCal in the user agent
-        //$ua = $this->server->httpRequest->getHeader('User-Agent');
-        //if (strpos($ua,'iCal/')!==false) {
-        //    throw new \Sabre\DAV\Exception\Forbidden('iCal has major bugs in it\'s RFC3744 support. Therefore we are left with no other choice but disabling this feature.');
-        //}
-
         $body = $request->getBodyAsString();
         $path = $request->getPath();
 
@@ -264,16 +260,9 @@ class Plugin extends DAV\ServerPlugin {
 
         if ($body) {
 
-            $dom = DAV\XMLUtil::loadDOMDocument($body);
-
-            foreach($dom->firstChild->childNodes as $child) {
+            $mkcalendar = $this->server->xml->parse($body);
+            $properties = $mkcalendar['value']->getProperties();
 
-                if (DAV\XMLUtil::toClarkNotation($child)!=='{DAV:}set') continue;
-                foreach(DAV\XMLUtil::parseProperties($child,$this->server->propertyMap) as $k=>$prop) {
-                    $properties[$k] = $prop;
-                }
-
-            }
         }
 
         // iCal abuses MKCALENDAR since iCal 10.9.2 to create server-stored
diff --git a/lib/CalDAV/Subscriptions/Plugin.php b/lib/CalDAV/Subscriptions/Plugin.php
index 968a795..4f7b961 100644
--- a/lib/CalDAV/Subscriptions/Plugin.php
+++ b/lib/CalDAV/Subscriptions/Plugin.php
@@ -39,6 +39,9 @@ class Plugin extends ServerPlugin {
         $server->propertyMap['{http://calendarserver.org/ns/}source'] =
             'Sabre\\DAV\\Property\\Href';
 
+        $server->xml->elementMap['{http://calendarserver.org/ns/}source'] =
+            'Sabre\\DAV\\Xml\\Property\\Href';
+
         $server->on('propFind', [$this, 'propFind'], 150);
 
     }
diff --git a/lib/CalDAV/Subscriptions/Subscription.php b/lib/CalDAV/Subscriptions/Subscription.php
index 14831e5..d3f5356 100644
--- a/lib/CalDAV/Subscriptions/Subscription.php
+++ b/lib/CalDAV/Subscriptions/Subscription.php
@@ -160,7 +160,7 @@ class Subscription extends Collection implements ISubscription, IACL {
                     $r[$prop] = new Href($this->subscriptionInfo['source'], false);
                     break;
                 default :
-                    if (isset($this->subscriptionInfo[$prop])) {
+                    if (array_key_exists($prop,$this->subscriptionInfo)) {
                         $r[$prop] = $this->subscriptionInfo[$prop];
                     }
                     break;
diff --git a/lib/CalDAV/Xml/CalendarData.php b/lib/CalDAV/Xml/CalendarData.php
new file mode 100644
index 0000000..1788bb8
--- /dev/null
+++ b/lib/CalDAV/Xml/CalendarData.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace Sabre\CalDAV\XML;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\DAV\Exception\BadRequest,
+    Sabre\CalDAV\Plugin,
+    Sabre\VObject\DateTimeParser;
+
+
+/**
+ * CalendarData parser.
+ *
+ * This class parses the {urn:ietf:params:xml:ns:caldav}calendar-data XML
+ * element, as defined in:
+ *
+ * https://tools.ietf.org/html/rfc4791#section-9.6
+ *
+ * This element is used for three distinct purposes:
+ *
+ * 1. To return calendar-data in a response, in which case this deserializer
+ *    will just spit out a string.
+ * 2. Information on how calendar-data should be returned, from a
+ *    calendar-multiget or calendar-query REPORT, in which case this
+ *    deserializer will spit out and array with the relevant information.
+ * 3. A list of supported media-types, nested in the supported-calendar-data
+ *    property. This case is currently not handled.
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class CalendarData implements Element {
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        throw new CannotSerialize('This element cannot be serialized.');
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $value = $reader->parseInnerTree();
+
+        // If we are parsing this as a string, it must have been an iCalendar
+        // blob, and we can just return it as-is.
+        if (is_string($value) || is_null($value)) {
+            return $value;
+        }
+
+        $result = [
+        ];
+        foreach($value as $elem) {
+
+            if ($elem['name'] === '{' . Plugin::NS_CALDAV . '}expand') {
+
+                $result['expand'] = [
+                    'start' => isset($elem['attributes']['start'])?DateTimeParser::parseDateTime($elem['attributes']['start']):null,
+                    'end' => isset($elem['attributes']['end'])?DateTimeParser::parseDateTime($elem['attributes']['end']):null,
+                ];
+
+                if (!$result['expand']['start'] || !$result['expand']['end']) {
+                    throw new BadRequest('The "start" and "end" attributes are required when expanding calendar-data');
+                }
+                if ($result['expand']['end'] <= $result['expand']['start']) {
+                    throw new BadRequest('The end-date must be larger than the start-date when expanding calendar-data');
+                }
+
+            }
+
+        }
+
+        return $result;
+
+    }
+
+}
diff --git a/lib/CalDAV/Xml/Filter/CompFilter.php b/lib/CalDAV/Xml/Filter/CompFilter.php
new file mode 100644
index 0000000..36ebe8a
--- /dev/null
+++ b/lib/CalDAV/Xml/Filter/CompFilter.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Filter;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\DAV\Exception\BadRequest,
+    Sabre\CalDAV\Plugin,
+    Sabre\VObject\DateTimeParser;
+
+
+/**
+ * CompFilter parser.
+ *
+ * This class parses the {urn:ietf:params:xml:ns:caldav}comp-filter XML
+ * element, as defined in:
+ *
+ * https://tools.ietf.org/html/rfc4791#section-9.6
+ *
+ * The result will be spit out as an array.
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class CompFilter implements Element {
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        throw new CannotSerialize('This element cannot be serialized.');
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $result = [
+            'name' => null,
+            'is-not-defined' => false,
+            'comp-filters' => [],
+            'prop-filters' => [],
+            'time-range' => false,
+        ];
+
+        $att = $reader->parseAttributes();
+        $result['name'] = $att['name'];
+
+        $elems = $reader->parseInnerTree();
+
+        if (is_array($elems)) foreach($elems as $elem) {
+
+            switch($elem['name']) {
+
+                case '{' . Plugin::NS_CALDAV . '}comp-filter' :
+                    $result['comp-filters'][] = $elem['value'];
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}prop-filter' :
+                    $result['prop-filters'][] = $elem['value'];
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}is-not-defined' :
+                    $result['is-not-defined'] = true;
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}time-range' :
+                    if ($result['name'] === 'VCALENDAR') {
+                        throw new BadRequest('You cannot add time-range filters on the VCALENDAR component');
+                    }
+                    $result['time-range'] = [
+                        'start' => isset($elem['attributes']['start'])?DateTimeParser::parseDateTime($elem['attributes']['start']):null,
+                        'end' => isset($elem['attributes']['end'])?DateTimeParser::parseDateTime($elem['attributes']['end']):null,
+                    ];
+                    if($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) {
+                        throw new BadRequest('The end-date must be larger than the start-date');
+                    }
+                    break;
+                default :
+                    die('Unknown!' . $elem['name']);
+
+            }
+
+        }
+
+        return $result;
+
+    }
+
+}
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/CalDAV/Xml/Filter/ParamFilter.php
similarity index 54%
copy from lib/DAV/Xml/Request/MkCol.php
copy to lib/CalDAV/Xml/Filter/ParamFilter.php
index d8d52652..feb0a59 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/CalDAV/Xml/Filter/ParamFilter.php
@@ -1,32 +1,32 @@
 <?php
 
-namespace Sabre\DAV\Xml\Request;
+namespace Sabre\CalDAV\Xml\Filter;
 
 use
     Sabre\Xml\Element,
     Sabre\Xml\Reader,
     Sabre\Xml\Writer,
-    Sabre\DAV\Exception\CannotSerialize;
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\DAV\Exception\BadRequest,
+    Sabre\CalDAV\Plugin,
+    Sabre\VObject\DateTimeParser;
+
 
 /**
- * WebDAV Extended MKCOL request parser.
+ * PropFilter parser.
+ *
+ * This class parses the {urn:ietf:params:xml:ns:caldav}param-filter XML
+ * element, as defined in:
  *
- * This class parses the {DAV:}mkol request, as defined in:
+ * https://tools.ietf.org/html/rfc4791#section-9.7.3
  *
- * https://tools.ietf.org/html/rfc5689#section-5.1
+ * The result will be spit out as an array.
  *
  * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class MkCol implements Element {
-
-    /**
-     * The list of properties that will be set.
-     *
-     * @var array
-     */
-    public $properties = [];
+class ParamFilter implements Element {
 
     /**
      * The serialize method is called during xml writing.
@@ -43,7 +43,7 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    public function serializeXml(Writer $writer) {
 
         throw new CannotSerialize('This element cannot be serialized.');
 
@@ -70,19 +70,39 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static public function deserializeXml(Reader $reader) {
 
-        $self = new self();
+        $result = [
+            'name' => null,
+            'is-not-defined' => false,
+            'text-match' => null,
+        ];
+
+        $att = $reader->parseAttributes();
+        $result['name'] = $att['name'];
 
         $elems = $reader->parseInnerTree();
 
-        foreach($elems as $elem) {
-            if ($elem['name'] === '{DAV:}set') {
-                $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
+        if (is_array($elems)) foreach($elems as $elem) {
+
+            switch($elem['name']) {
+
+                case '{' . Plugin::NS_CALDAV . '}is-not-defined' :
+                    $result['is-not-defined'] = true;
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}text-match' :
+                    $result['text-match'] = [
+                        'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition']==='yes',
+                        'collation'        => isset($elem['attributes']['collation'])?$elem['attributes']['collation']:'i;ascii-casemap',
+                        'value'            => $elem['value'],
+                    ];
+                    break;
+
             }
+
         }
 
-        return $self;
+        return $result;
 
     }
 
diff --git a/lib/CalDAV/Xml/Filter/PropFilter.php b/lib/CalDAV/Xml/Filter/PropFilter.php
new file mode 100644
index 0000000..773b322
--- /dev/null
+++ b/lib/CalDAV/Xml/Filter/PropFilter.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Filter;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\DAV\Exception\BadRequest,
+    Sabre\CalDAV\Plugin,
+    Sabre\VObject\DateTimeParser;
+
+
+/**
+ * PropFilter parser.
+ *
+ * This class parses the {urn:ietf:params:xml:ns:caldav}prop-filter XML
+ * element, as defined in:
+ *
+ * https://tools.ietf.org/html/rfc4791#section-9.7.2
+ *
+ * The result will be spit out as an array.
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class PropFilter implements Element {
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        throw new CannotSerialize('This element cannot be serialized.');
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $result = [
+            'name' => null,
+            'is-not-defined' => false,
+            'param-filters' => [],
+            'text-match' => null,
+            'time-range' => false,
+        ];
+
+        $att = $reader->parseAttributes();
+        $result['name'] = $att['name'];
+
+        $elems = $reader->parseInnerTree();
+
+        if (is_array($elems)) foreach($elems as $elem) {
+
+            switch($elem['name']) {
+
+                case '{' . Plugin::NS_CALDAV . '}param-filter' :
+                    $result['param-filters'][] = $elem['value'];
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}is-not-defined' :
+                    $result['is-not-defined'] = true;
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}time-range' :
+                    if ($result['name'] === 'VCALENDAR') {
+                        throw new BadRequest('You cannot add time-range filters on the VCALENDAR component');
+                    }
+                    $result['time-range'] = [
+                        'start' => isset($elem['attributes']['start'])?DateTimeParser::parseDateTime($elem['attributes']['start']):null,
+                        'end' => isset($elem['attributes']['end'])?DateTimeParser::parseDateTime($elem['attributes']['end']):null,
+                    ];
+                    if($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) {
+                        throw new BadRequest('The end-date must be larger than the start-date');
+                    }
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}text-match' :
+                    $result['text-match'] = [
+                        'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition']==='yes',
+                        'collation'        => isset($elem['attributes']['collation'])?$elem['attributes']['collation']:'i;ascii-casemap',
+                        'value'            => $elem['value'],
+                    ];
+                    break;
+                default :
+                    die('Unknown!' . $elem['name']);
+
+            }
+
+        }
+
+        return $result;
+
+    }
+
+}
diff --git a/lib/CalDAV/Xml/Notification/Invite.php b/lib/CalDAV/Xml/Notification/Invite.php
new file mode 100644
index 0000000..53336a3
--- /dev/null
+++ b/lib/CalDAV/Xml/Notification/Invite.php
@@ -0,0 +1,334 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Notification;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\CalDAV\SharingPlugin as SharingPlugin,
+    Sabre\DAV,
+    Sabre\CalDAV;
+
+/**
+ * This class represents the cs:invite-notification notification element.
+ *
+ * This element is defined here:
+ * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
+ *
+ * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Invite implements NotificationInterface {
+
+    /**
+     * A unique id for the message
+     *
+     * @var string
+     */
+    protected $id;
+
+    /**
+     * Timestamp of the notification
+     *
+     * @var DateTime
+     */
+    protected $dtStamp;
+
+    /**
+     * A url to the recipient of the notification. This can be an email
+     * address (mailto:), or a principal url.
+     *
+     * @var string
+     */
+    protected $href;
+
+    /**
+     * The type of message, see the SharingPlugin::STATUS_* constants.
+     *
+     * @var int
+     */
+    protected $type;
+
+    /**
+     * True if access to a calendar is read-only.
+     *
+     * @var bool
+     */
+    protected $readOnly;
+
+    /**
+     * A url to the shared calendar.
+     *
+     * @var string
+     */
+    protected $hostUrl;
+
+    /**
+     * Url to the sharer of the calendar
+     *
+     * @var string
+     */
+    protected $organizer;
+
+    /**
+     * The name of the sharer.
+     *
+     * @var string
+     */
+    protected $commonName;
+
+    /**
+     * The name of the sharer.
+     *
+     * @var string
+     */
+    protected $firstName;
+
+    /**
+     * The name of the sharer.
+     *
+     * @var string
+     */
+    protected $lastName;
+
+    /**
+     * A description of the share request
+     *
+     * @var string
+     */
+    protected $summary;
+
+    /**
+     * The Etag for the notification
+     *
+     * @var string
+     */
+    protected $etag;
+
+    /**
+     * The list of supported components
+     *
+     * @var Sabre\CalDAV\Property\SupportedCalendarComponentSet
+     */
+    protected $supportedComponents;
+
+    /**
+     * Creates the Invite notification.
+     *
+     * This constructor receives an array with the following elements:
+     *
+     *   * id           - A unique id
+     *   * etag         - The etag
+     *   * dtStamp      - A DateTime object with a timestamp for the notification.
+     *   * type         - The type of notification, see SharingPlugin::STATUS_*
+     *                    constants for details.
+     *   * readOnly     - This must be set to true, if this is an invite for
+     *                    read-only access to a calendar.
+     *   * hostUrl      - A url to the shared calendar.
+     *   * organizer    - Url to the sharer principal.
+     *   * commonName   - The real name of the sharer (optional).
+     *   * firstName    - The first name of the sharer (optional).
+     *   * lastName     - The last name of the sharer (optional).
+     *   * summary      - Description of the share, can be the same as the
+     *                    calendar, but may also be modified (optional).
+     *   * supportedComponents - An instance of
+     *                    Sabre\CalDAV\Property\SupportedCalendarComponentSet.
+     *                    This allows the client to determine which components
+     *                    will be supported in the shared calendar. This is
+     *                    also optional.
+     *
+     * @param array $values All the options
+     */
+    public function __construct(array $values) {
+
+        $required = array(
+            'id',
+            'etag',
+            'href',
+            'dtStamp',
+            'type',
+            'readOnly',
+            'hostUrl',
+            'organizer',
+        );
+        foreach($required as $item) {
+            if (!isset($values[$item])) {
+                throw new \InvalidArgumentException($item . ' is a required constructor option');
+            }
+        }
+
+        foreach($values as $key=>$value) {
+            if (!property_exists($this, $key)) {
+                throw new \InvalidArgumentException('Unknown option: ' . $key);
+            }
+            $this->$key = $value;
+        }
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        $writer->writeElement('{' . CalDAV\Plugin::NS_CALENDARSERVER .'}invite-notification');
+
+    }
+
+    /**
+     * This method serializes the entire notification, as it is used in the
+     * response body.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeFullXml(Writer $writer) {
+
+        $cs = '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}';
+
+        $this->dtStamp->setTimezone(new \DateTimezone('GMT'));
+        $writer->writeElement($cs . 'dtstamp', $this->dtStamp->format('Ymd\\THis\\Z'));
+
+        $writer->startElement($cs . 'invite-notification');
+
+        $writer->writeElement($cs . 'uid', $this->id);
+        $writer->writeElement('{DAV:}href', $this->href);
+
+        switch($this->type) {
+
+            case SharingPlugin::STATUS_ACCEPTED :
+                $writer->writeElement($cs . 'invite-accepted');
+                break;
+            case SharingPlugin::STATUS_DECLINED :
+                $writer->writeElement($cs . 'invite-declined');
+                break;
+            case SharingPlugin::STATUS_DELETED :
+                $writer->writeElement($cs . 'invite-deleted');
+                break;
+            case SharingPlugin::STATUS_NORESPONSE :
+                $writer->writeElement($cs . 'invite-noresponse');
+                break;
+
+        }
+
+        $writer->writeElement($cs . 'hosturl', [
+            '{DAV:}href' => $writer->baseUri . $this->hostUrl
+            ]);
+
+        if ($this->summary) {
+            $writer->writeElement($cs . 'summary', $this->summary);
+        }
+
+        $writer->startElement($cs . 'access');
+        if ($this->readOnly) {
+            $writer->writeElement($cs . 'read');
+        } else {
+            $writer->writeElement($cs . 'read-write');
+        }
+        $writer->endElement(); // access
+
+        $writer->startElement($cs . 'organizer');
+        // If the organizer contains a 'mailto:' part, it means it should be
+        // treated as absolute.
+        if (strtolower(substr($this->organizer,0,7))==='mailto:') {
+            $writer->writeElement('{DAV:}href',$this->organizer);
+        } else {
+            $writer->writeElement('{DAV:}href',$writer->baseUri . $this->organizer);
+        }
+        if ($this->commonName) {
+            $writer->writeElement($cs . 'common-name', $this->commonName);
+        }
+        if ($this->firstName) {
+            $writer->writeElement($cs . 'first-name', $this->firstName);
+        }
+        if ($this->lastName) {
+            $writer->writeElement($cs . 'last-name', $this->lastName);
+        }
+        $writer->endElement(); // organizer
+
+        if ($this->commonName) {
+            $writer->writeElement($cs . 'organizer-cn', $this->commonName);
+        }
+        if ($this->firstName) {
+            $writer->writeElement($cs . 'organizer-first', $this->firstName);
+        }
+        if ($this->lastName) {
+            $writer->writeElement($cs . 'organizer-last', $this->lastName);
+        }
+        if ($this->supportedComponents) {
+            $writer->writeElement('{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set', $this->supportedComponents);
+        }
+
+        $writer->endElement(); // invite-notification
+
+    }
+
+    /**
+     * Returns a unique id for this notification
+     *
+     * This is just the base url. This should generally be some kind of unique
+     * id.
+     *
+     * @return string
+     */
+    public function getId() {
+
+        return $this->id;
+
+    }
+
+    /**
+     * Returns the ETag for this notification.
+     *
+     * The ETag must be surrounded by literal double-quotes.
+     *
+     * @return string
+     */
+    public function getETag() {
+
+        return $this->etag;
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        throw new CannotDeserialize('This element does not have a deserializer');
+
+    }
+
+}
diff --git a/lib/CalDAV/Xml/Notification/InviteReply.php b/lib/CalDAV/Xml/Notification/InviteReply.php
new file mode 100644
index 0000000..d6067a7
--- /dev/null
+++ b/lib/CalDAV/Xml/Notification/InviteReply.php
@@ -0,0 +1,237 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Notification;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\DAV,
+    Sabre\CalDAV,
+    Sabre\CalDAV\SharingPlugin;
+
+/**
+ * This class represents the cs:invite-reply notification element.
+ *
+ * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class InviteReply implements NotificationInterface {
+
+    /**
+     * A unique id for the message
+     *
+     * @var string
+     */
+    protected $id;
+
+    /**
+     * Timestamp of the notification
+     *
+     * @var DateTime
+     */
+    protected $dtStamp;
+
+    /**
+     * The unique id of the notification this was a reply to.
+     *
+     * @var string
+     */
+    protected $inReplyTo;
+
+    /**
+     * A url to the recipient of the original (!) notification.
+     *
+     * @var string
+     */
+    protected $href;
+
+    /**
+     * The type of message, see the SharingPlugin::STATUS_ constants.
+     *
+     * @var int
+     */
+    protected $type;
+
+    /**
+     * A url to the shared calendar.
+     *
+     * @var string
+     */
+    protected $hostUrl;
+
+    /**
+     * A description of the share request
+     *
+     * @var string
+     */
+    protected $summary;
+
+    /**
+     * Notification Etag
+     *
+     * @var string
+     */
+    protected $etag;
+
+    /**
+     * Creates the Invite Reply Notification.
+     *
+     * This constructor receives an array with the following elements:
+     *
+     *   * id           - A unique id
+     *   * etag         - The etag
+     *   * dtStamp      - A DateTime object with a timestamp for the notification.
+     *   * inReplyTo    - This should refer to the 'id' of the notification
+     *                    this is a reply to.
+     *   * type         - The type of notification, see SharingPlugin::STATUS_*
+     *                    constants for details.
+     *   * hostUrl      - A url to the shared calendar.
+     *   * summary      - Description of the share, can be the same as the
+     *                    calendar, but may also be modified (optional).
+     */
+    public function __construct(array $values) {
+
+        $required = array(
+            'id',
+            'etag',
+            'href',
+            'dtStamp',
+            'inReplyTo',
+            'type',
+            'hostUrl',
+        );
+        foreach($required as $item) {
+            if (!isset($values[$item])) {
+                throw new \InvalidArgumentException($item . ' is a required constructor option');
+            }
+        }
+
+        foreach($values as $key=>$value) {
+            if (!property_exists($this, $key)) {
+                throw new \InvalidArgumentException('Unknown option: ' . $key);
+            }
+            $this->$key = $value;
+        }
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        $writer->writeElement('{' . CalDAV\Plugin::NS_CALENDARSERVER .'}invite-reply');
+
+    }
+
+    /**
+     * This method serializes the entire notification, as it is used in the
+     * response body.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeFullXml(Writer $writer) {
+
+        $cs = '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}';
+
+        $this->dtStamp->setTimezone(new \DateTimezone('GMT'));
+        $writer->writeElement($cs . 'dtstamp', $this->dtStamp->format('Ymd\\THis\\Z'));
+
+        $writer->startElement($cs . 'invite-reply');
+
+        $writer->writeElement($cs . 'uid', $this->id);
+        $writer->writeElement($cs . 'in-reply-to', $this->inReplyTo);
+        $writer->writeElement('{DAV:}href', $this->href);
+
+        switch($this->type) {
+
+            case SharingPlugin::STATUS_ACCEPTED :
+                $writer->writeElement($cs . 'invite-accepted');
+                break;
+            case SharingPlugin::STATUS_DECLINED :
+                $writer->writeElement($cs . 'invite-declined');
+                break;
+
+        }
+
+        $writer->writeElement($cs . 'hosturl', [
+            '{DAV:}href' => $writer->baseUri . $this->hostUrl
+            ]);
+
+        if ($this->summary) {
+            $writer->writeElement($cs . 'summary', $this->summary);
+        }
+        $writer->endElement(); // invite-reply
+
+    }
+
+    /**
+     * Returns a unique id for this notification
+     *
+     * This is just the base url. This should generally be some kind of unique
+     * id.
+     *
+     * @return string
+     */
+    public function getId() {
+
+        return $this->id;
+
+    }
+
+    /**
+     * Returns the ETag for this notification.
+     *
+     * The ETag must be surrounded by literal double-quotes.
+     *
+     * @return string
+     */
+    public function getETag() {
+
+        return $this->etag;
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        throw new CannotDeserialize('This element does not have a deserializer');
+
+    }
+
+}
diff --git a/lib/CalDAV/Xml/Notification/NotificationInterface.php b/lib/CalDAV/Xml/Notification/NotificationInterface.php
new file mode 100644
index 0000000..c49d47b
--- /dev/null
+++ b/lib/CalDAV/Xml/Notification/NotificationInterface.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Notification;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Writer;
+
+/**
+ * This interface reflects a single notification type.
+ *
+ * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface NotificationInterface extends Element {
+
+    /**
+     * This method serializes the entire notification, as it is used in the
+     * response body.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    function serializeFullXml(Writer $writer);
+
+    /**
+     * Returns a unique id for this notification
+     *
+     * This is just the base url. This should generally be some kind of unique
+     * id.
+     *
+     * @return string
+     */
+    function getId();
+
+    /**
+     * Returns the ETag for this notification.
+     *
+     * The ETag must be surrounded by literal double-quotes.
+     *
+     * @return string
+     */
+    function getETag();
+
+}
diff --git a/lib/CalDAV/Xml/Notification/SystemStatus.php b/lib/CalDAV/Xml/Notification/SystemStatus.php
new file mode 100644
index 0000000..4855164
--- /dev/null
+++ b/lib/CalDAV/Xml/Notification/SystemStatus.php
@@ -0,0 +1,212 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Notification;
+
+use
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\CalDAV\Plugin,
+    Sabre\DAV\Exception\CannotSerialize;
+
+
+/**
+ * SystemStatus notification
+ *
+ * This notification can be used to indicate to the user that the system is
+ * down.
+ *
+ * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class SystemStatus implements NotificationInterface {
+
+    const TYPE_LOW = 1;
+    const TYPE_MEDIUM = 2;
+    const TYPE_HIGH = 3;
+
+    /**
+     * A unique id
+     *
+     * @var string
+     */
+    protected $id;
+
+    /**
+     * The type of alert. This should be one of the TYPE_ constants.
+     *
+     * @var int
+     */
+    protected $type;
+
+    /**
+     * A human-readable description of the problem.
+     *
+     * @var string
+     */
+    protected $description;
+
+    /**
+     * A url to a website with more information for the user.
+     *
+     * @var string
+     */
+    protected $href;
+
+    /**
+     * Notification Etag
+     *
+     * @var string
+     */
+    protected $etag;
+
+    /**
+     * Creates the notification.
+     *
+     * Some kind of unique id should be provided. This is used to generate a
+     * url.
+     *
+     * @param string $id
+     * @param string $etag
+     * @param int $type
+     * @param string $description
+     * @param string $href
+     */
+    public function __construct($id, $etag, $type = self::TYPE_HIGH, $description = null, $href = null) {
+
+        $this->id = $id;
+        $this->type = $type;
+        $this->description = $description;
+        $this->href = $href;
+        $this->etag = $etag;
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        switch($this->type) {
+            case self::TYPE_LOW :
+                $type = 'low';
+                break;
+            case self::TYPE_MEDIUM :
+                $type = 'medium';
+                break;
+            default :
+            case self::TYPE_HIGH :
+                $type = 'high';
+                break;
+        }
+
+        $writer->startElement('{' . Plugin::NS_CALENDARSERVER .'}systemstatus');
+        $writer->writeAttribute('type', $type);
+        $writer->endElement();
+
+    }
+
+    /**
+     * This method serializes the entire notification, as it is used in the
+     * response body.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeFullXml(Writer $writer) {
+
+        $cs = '{' . Plugin::NS_CALENDARSERVER .'}';
+        switch($this->type) {
+            case self::TYPE_LOW :
+                $type = 'low';
+                break;
+            case self::TYPE_MEDIUM :
+                $type = 'medium';
+                break;
+            default :
+            case self::TYPE_HIGH :
+                $type = 'high';
+                break;
+        }
+
+        $writer->startElement($cs .'systemstatus');
+        $writer->writeAttribute('type', $type);
+
+
+        if ($this->description) {
+            $writer->writeElement($cs . 'description', $this->description);
+        }
+        if ($this->href) {
+            $writer->writeElement('{DAV:}href', $this->href);
+        }
+
+        $writer->endElement(); // systemstatus
+
+    }
+
+    /**
+     * Returns a unique id for this notification
+     *
+     * This is just the base url. This should generally be some kind of unique
+     * id.
+     *
+     * @return string
+     */
+    public function getId() {
+
+        return $this->id;
+
+    }
+
+    /*
+     * Returns the ETag for this notification.
+     *
+     * The ETag must be surrounded by literal double-quotes.
+     *
+     * @return string
+     */
+    public function getETag() {
+
+        return $this->etag;
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        throw new CannotDeserialize('This element does not have a deserializer');
+
+    }
+}
diff --git a/lib/DAV/Xml/Property/SupportedLock.php b/lib/CalDAV/Xml/Property/AllowedSharingModes.php
similarity index 54%
copy from lib/DAV/Xml/Property/SupportedLock.php
copy to lib/CalDAV/Xml/Property/AllowedSharingModes.php
index 979442c..f560a7d 100644
--- a/lib/DAV/Xml/Property/SupportedLock.php
+++ b/lib/CalDAV/Xml/Property/AllowedSharingModes.php
@@ -1,43 +1,57 @@
 <?php
 
-namespace Sabre\DAV\Xml\Property;
+namespace Sabre\CalDAV\Xml\Property;
 
 use
-    Sabre\DAV,
     Sabre\Xml\Element,
     Sabre\Xml\Reader,
-    Sabre\Xml\Writer;
+    Sabre\Xml\Writer,
+    Sabre\DAV\Exception\CannotDeserialize,
+    Sabre\CalDAV\Plugin;
 
 /**
- * This class represents the {DAV:}supportedlock property.
+ * AllowedSharingModes
  *
- * This property is defined here:
- * http://tools.ietf.org/html/rfc4918#section-15.10
+ * This property encodes the 'allowed-sharing-modes' property, as defined by
+ * the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
+ * namespace.
  *
- * This property contains information about what kind of locks
- * this server supports.
+ * This property is a representation of the supported-calendar_component-set
+ * property in the CalDAV namespace. It simply requires an array of components,
+ * such as VEVENT, VTODO
  *
+ * @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
  * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class SupportedLock implements Element {
+class AllowedSharingModes implements Element {
 
     /**
-     * supportsLocks
+     * Whether or not a calendar can be shared with another user
      *
      * @var bool
      */
-    public $supportsLocks = false;
+    protected $canBeShared;
 
     /**
-     * __construct
+     * Whether or not the calendar can be placed on a public url.
      *
-     * @param bool $supportsLocks
+     * @var bool
+     */
+    protected $canBePublished;
+
+    /**
+     * Constructor
+     *
+     * @param bool $canBeShared
+     * @param bool $canBePublished
+     * @return void
      */
-    public function __construct($supportsLocks) {
+    public function __construct($canBeShared, $canBePublished) {
 
-        $this->supportsLocks = $supportsLocks;
+        $this->canBeShared = $canBeShared;
+        $this->canBePublished = $canBePublished;
 
     }
 
@@ -56,18 +70,14 @@ class SupportedLock implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    public function serializeXml(Writer $writer) {
 
-        if (!$this->supportsLocks) return null;
-
-        $writer->writeElement('{DAV:}lockentry', [
-            '{DAV:}lockscope' => ['{DAV:}exclusive' => null],        
-            '{DAV:}locktype' =>  ['{DAV:}write' => null],        
-        ]);
-        $writer->writeElement('{DAV:}lockentry', [
-            '{DAV:}lockscope' => ['{DAV:}shared' => null],        
-            '{DAV:}locktype' =>  ['{DAV:}write' => null],        
-        ]);
+        if ($this->canBeShared) {
+            $writer->writeElement('{' . Plugin::NS_CALENDARSERVER . '}can-be-shared');
+        }
+        if ($this->canBePublished) {
+            $writer->writeElement('{' . Plugin::NS_CALENDARSERVER . '}can-be-published');
+        }
 
     }
 
@@ -92,10 +102,9 @@ class SupportedLock implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static public function deserializeXml(Reader $reader) {
 
         throw new CannotDeserialize('This element does not have a deserializer');
 
     }
 }
-
diff --git a/lib/CalDAV/Xml/Property/Invite.php b/lib/CalDAV/Xml/Property/Invite.php
new file mode 100644
index 0000000..f40a813
--- /dev/null
+++ b/lib/CalDAV/Xml/Property/Invite.php
@@ -0,0 +1,250 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Property;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\CalDAV\Plugin,
+    Sabre\CalDAV\SharingPlugin;
+
+/**
+ * Invite property
+ *
+ * This property encodes the 'invite' property, as defined by
+ * the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
+ * namespace.
+ *
+ * @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Invite implements Element {
+
+    /**
+     * The list of users a calendar has been shared to.
+     *
+     * @var array
+     */
+    protected $users;
+
+    /**
+     * The organizer contains information about the person who shared the
+     * object.
+     *
+     * @var array
+     */
+    protected $organizer;
+
+    /**
+     * Creates the property.
+     *
+     * Users is an array. Each element of the array has the following
+     * properties:
+     *
+     *   * href - Often a mailto: address
+     *   * commonName - Optional, for example a first and lastname for a user.
+     *   * status - One of the SharingPlugin::STATUS_* constants.
+     *   * readOnly - true or false
+     *   * summary - Optional, description of the share
+     *
+     * The organizer key is optional to specify. It's only useful when a
+     * 'sharee' requests the sharing information.
+     *
+     * The organizer may have the following properties:
+     *   * href - Often a mailto: address.
+     *   * commonName - Optional human-readable name.
+     *   * firstName - Optional first name.
+     *   * lastName - Optional last name.
+     *
+     * If you wonder why these two structures are so different, I guess a
+     * valid answer is that the current spec is still a draft.
+     *
+     * @param array $users
+     */
+    public function __construct(array $users, array $organizer = null) {
+
+        $this->users = $users;
+        $this->organizer = $organizer;
+
+    }
+
+    /**
+     * Returns the list of users, as it was passed to the constructor.
+     *
+     * @return array
+     */
+    public function getValue() {
+
+        return $this->users;
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        $cs = '{' . Plugin::NS_CALENDARSERVER . '}';
+
+        if (!is_null($this->organizer)) {
+
+            $writer->startElement($cs . 'organizer');
+            $writer->writeElement('{DAV:}href', $this->organizer['href']);
+
+            if (isset($this->organizer['commonName']) && $this->organizer['commonName']) {
+                $writer->writeElement($cs . 'common-name', $this->organizer['commonName']);
+            }
+            if (isset($this->organizer['firstName']) && $this->organizer['firstName']) {
+                $writer->writeElement($cs . 'first-name', $this->organizer['firstName']);
+            }
+            if (isset($this->organizer['lastName']) && $this->organizer['lastName']) {
+                $writer->writeElement($cs . 'last-name', $this->organizer['lastName']);
+            }
+            $writer->endElement(); // organizer
+
+        }
+
+        foreach($this->users as $user) {
+
+            $writer->startElement($cs . 'user');
+            $writer->writeElement('{DAV:}href', $user['href']);
+            if (isset($user['commonName']) && $user['commonName']) {
+                $writer->writeElement($cs . 'common-name', $user['commonName']);
+            }
+            switch($user['status']) {
+
+                case SharingPlugin::STATUS_ACCEPTED :
+                    $writer->writeElement($cs . 'invite-accepted');
+                    break;
+                case SharingPlugin::STATUS_DECLINED :
+                    $writer->writeElement($cs . 'invite-declined');
+                    break;
+                case SharingPlugin::STATUS_NORESPONSE :
+                    $writer->writeElement($cs . 'invite-noresponse');
+                    break;
+                case SharingPlugin::STATUS_INVALID :
+                    $writer->writeElement($cs . 'invite-invalid');
+                    break;
+            }
+
+            $writer->startElement($cs . 'access');
+            if ($user['readOnly']) {
+                $writer->writeElement($cs . 'read');
+            } else {
+                $writer->writeElement($cs . 'read-write');
+            }
+            $writer->endElement(); // access
+
+            if (isset($user['summary']) && $user['summary']) {
+                $writer->writeElement($cs . 'summary', $user['summary']);
+            }
+
+            $writer->endElement(); //user
+
+       }
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $cs = '{' . Plugin::NS_CALENDARSERVER . '}';
+
+        $users = [];
+
+        foreach($reader->parseInnerTree() as $elem) {
+
+            if ($elem['name']!==$cs.'user')
+                continue;
+
+            $user = [
+                'href' => null,
+                'commonName' => null,
+                'readOnly' => null,
+                'summary' => null,
+                'status' => null,
+            ];
+
+            foreach($elem['value'] as $userElem) {
+
+                switch($userElem['name']) {
+                    case $cs . 'invite-accepted' :
+                        $user['status'] = SharingPlugin::STATUS_ACCEPTED;
+                        break;
+                    case $cs . 'invite-declined' :
+                        $user['status'] = SharingPlugin::STATUS_DECLINED;
+                        break;
+                    case $cs . 'invite-noresponse' :
+                        $user['status'] = SharingPlugin::STATUS_NORESPONSE;
+                        break;
+                    case $cs . 'invite-invalid' :
+                        $user['status'] = SharingPlugin::STATUS_INVALID;
+                        break;
+                    case '{DAV:}href' :
+                        $user['href'] = $userElem['value'];
+                        break;
+                    case $cs . 'common-name' :
+                        $user['commonName'] = $userElem['value'];
+                        break;
+                    case $cs . 'access' :
+                        foreach($userElem['value'] as $accessHref) {
+                            if ($accessHref['name'] === $cs . 'read') {
+                                $user['readOnly'] = true;
+                            }
+                        }
+                        break;
+                    case $cs . 'summary' :
+                        $user['summary'] = $userElem['value'];
+                        break;
+
+                }
+
+            }
+            if (!$user['status']) {
+                throw new \InvalidArgumentException('Every user must have one of cs:invite-accepted, cs:invite-declined, cs:invite-noresponse or cs:invite-invalid');
+            }
+
+            $users[] = $user;
+
+        }
+
+        return new self($users);
+
+    }
+
+}
diff --git a/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php b/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php
new file mode 100644
index 0000000..e3b7e6d
--- /dev/null
+++ b/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Property;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\Xml\Element\Elements,
+    Sabre\CalDAV\Plugin;
+
+/**
+ * schedule-calendar-transp property.
+ *
+ * This property is a representation of the schedule-calendar-transp property.
+ * This property is defined in:
+ *
+ * http://tools.ietf.org/html/rfc6638#section-9.1
+ *
+ * Its values are either 'transparent' or 'opaque'. If it's transparent, it
+ * means that this calendar will not be taken into consideration when a
+ * different user queries for free-busy information. If it's 'opaque', it will.
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class ScheduleCalendarTransp implements Element {
+
+    const TRANSPARENT = 'transparent';
+    const OPAQUE = 'opaque';
+
+    /**
+     * value
+     *
+     * @var string
+     */
+    protected $value;
+
+    /**
+     * Creates the property
+     *
+     * @param string $value
+     */
+    public function __construct($value) {
+
+        if ($value !== self::TRANSPARENT && $value !== self::OPAQUE) {
+            throw new \InvalidArgumentException('The value must either be specified as "transparent" or "opaque"');
+        }
+        $this->value = $value;
+
+    }
+
+    /**
+     * Returns the current value
+     *
+     * @return string
+     */
+    public function getValue() {
+
+        return $this->value;
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        switch($this->value) {
+            case self::TRANSPARENT :
+                $writer->writeElement('{'.Plugin::NS_CALDAV.'}transparent');
+                break;
+            case self::OPAQUE :
+                $writer->writeElement('{'.Plugin::NS_CALDAV.'}opaque');
+                break;
+        }
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $elems = Elements::deserializeXml($reader);
+
+        $value = null;
+
+        foreach($elems as $elem) {
+            switch($elem) {
+                case '{' . Plugin::NS_CALDAV . '}opaque' :
+                    $value = self::OPAQUE;
+                    break;
+                case '{' . Plugin::NS_CALDAV . '}transparent' :
+                    $value = self::TRANSPARENT;
+                    break;
+            }
+        }
+        if (is_null($value))
+           return null;
+
+        return new self($value);
+
+    }
+
+}
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/CalDAV/Xml/Property/SupportedCalendarComponentSet.php
similarity index 51%
copy from lib/DAV/Xml/Request/MkCol.php
copy to lib/CalDAV/Xml/Property/SupportedCalendarComponentSet.php
index d8d52652..c69bbea 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/CalDAV/Xml/Property/SupportedCalendarComponentSet.php
@@ -1,32 +1,58 @@
 <?php
 
-namespace Sabre\DAV\Xml\Request;
+namespace Sabre\CalDAV\Xml\Property;
 
 use
     Sabre\Xml\Element,
     Sabre\Xml\Reader,
     Sabre\Xml\Writer,
-    Sabre\DAV\Exception\CannotSerialize;
+    Sabre\CalDAV\Plugin;
 
 /**
- * WebDAV Extended MKCOL request parser.
+ * SupportedCalendarComponentSet property.
  *
- * This class parses the {DAV:}mkol request, as defined in:
+ * This class represents the
+ * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set property, as
+ * defined in:
  *
- * https://tools.ietf.org/html/rfc5689#section-5.1
+ * https://tools.ietf.org/html/rfc4791#section-5.2.3
  *
- * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
  */
-class MkCol implements Element {
+class SupportedCalendarComponentSet implements Element {
 
     /**
-     * The list of properties that will be set.
+     * List of supported components.
+     *
+     * This array will contain values such as VEVENT, VTODO and VJOURNAL.
      *
      * @var array
      */
-    public $properties = [];
+    protected $components = [];
+
+    /**
+     * Creates the property.
+     *
+     * @param array $components
+     */
+    function __construct(array $components) {
+
+        $this->components = $components;
+
+    }
+
+    /**
+     * Returns the list of supported components
+     *
+     * @return array
+     */
+    function getValue() {
+
+        return $this->components;
+
+    }
 
     /**
      * The serialize method is called during xml writing.
@@ -43,9 +69,15 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    function xmlSerialize(Writer $writer) {
 
-        throw new CannotSerialize('This element cannot be serialized.');
+       foreach($this->components as $component) {
+
+            $writer->startElement('{' . Plugin::NS_CALDAV . '}comp');
+            $writer->writeAttributes(['name' => $component]);
+            $writer->endElement();
+
+       }
 
     }
 
@@ -70,19 +102,19 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
-
-        $self = new self();
+    static function xmlDeserialize(Reader $reader) {
 
         $elems = $reader->parseInnerTree();
 
+        $components = [];
+
         foreach($elems as $elem) {
-            if ($elem['name'] === '{DAV:}set') {
-                $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
+            if ($elem['name'] === '{'.Plugin::NS_CALDAV . '}comp') {
+                $components[] = $elem['attributes']['name'];
             }
         }
 
-        return $self;
+        return new self($components);
 
     }
 
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/CalDAV/Xml/Property/SupportedCalendarData.php
similarity index 64%
copy from lib/DAV/Xml/Request/MkCol.php
copy to lib/CalDAV/Xml/Property/SupportedCalendarData.php
index d8d52652..702aa2a 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/CalDAV/Xml/Property/SupportedCalendarData.php
@@ -1,32 +1,29 @@
 <?php
 
-namespace Sabre\DAV\Xml\Request;
+namespace Sabre\CalDAV\Xml\Property;
 
 use
     Sabre\Xml\Element,
     Sabre\Xml\Reader,
     Sabre\Xml\Writer,
-    Sabre\DAV\Exception\CannotSerialize;
+    Sabre\DAV\Exception\CannotDeserialize,
+    Sabre\CalDAV\Plugin;
 
 /**
- * WebDAV Extended MKCOL request parser.
+ * Supported-calendar-data property
  *
- * This class parses the {DAV:}mkol request, as defined in:
+ * This property is a representation of the supported-calendar-data property
+ * in the CalDAV namespace. SabreDAV only has support for text/calendar;2.0
+ * so the value is currently hardcoded.
  *
- * https://tools.ietf.org/html/rfc5689#section-5.1
+ * This property is defined in:
+ * http://tools.ietf.org/html/rfc4791#section-5.2.4
  *
  * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class MkCol implements Element {
-
-    /**
-     * The list of properties that will be set.
-     *
-     * @var array
-     */
-    public $properties = [];
+class SupportedCalendarData implements Element {
 
     /**
      * The serialize method is called during xml writing.
@@ -43,9 +40,14 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    public function serializeXml(Writer $writer) {
 
-        throw new CannotSerialize('This element cannot be serialized.');
+        $writer->startElement('{' . Plugin::NS_CALDAV . '}calendar-data');
+        $writer->writeAttributes([
+            'content-type' => 'text/calendar',
+            'version' => '2.0',
+        ]);
+        $writer->endElement(); // calendar-data
 
     }
 
@@ -70,20 +72,9 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static public function deserializeXml(Reader $reader) {
 
-        $self = new self();
-
-        $elems = $reader->parseInnerTree();
-
-        foreach($elems as $elem) {
-            if ($elem['name'] === '{DAV:}set') {
-                $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
-            }
-        }
-
-        return $self;
+        throw new CannotDeserialize('This element does not have a deserializer');
 
     }
-
 }
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/CalDAV/Xml/Property/SupportedCollationSet.php
similarity index 66%
copy from lib/DAV/Xml/Request/MkCol.php
copy to lib/CalDAV/Xml/Property/SupportedCollationSet.php
index d8d52652..f033e46 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/CalDAV/Xml/Property/SupportedCollationSet.php
@@ -1,32 +1,28 @@
 <?php
 
-namespace Sabre\DAV\Xml\Request;
+namespace Sabre\CalDAV\Xml\Property;
 
 use
     Sabre\Xml\Element,
     Sabre\Xml\Reader,
     Sabre\Xml\Writer,
-    Sabre\DAV\Exception\CannotSerialize;
+    Sabre\DAV\Exception\CannotDeserialize,
+    Sabre\CalDAV\Plugin;
 
 /**
- * WebDAV Extended MKCOL request parser.
+ * supported-collation-set property
  *
- * This class parses the {DAV:}mkol request, as defined in:
+ * This property is a representation of the supported-collation-set property
+ * in the CalDAV namespace.
  *
- * https://tools.ietf.org/html/rfc5689#section-5.1
+ * This property is defined in:
+ * http://tools.ietf.org/html/rfc4791#section-7.5.1
  *
  * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class MkCol implements Element {
-
-    /**
-     * The list of properties that will be set.
-     *
-     * @var array
-     */
-    public $properties = [];
+class SupportedCollationSet implements Element {
 
     /**
      * The serialize method is called during xml writing.
@@ -43,9 +39,17 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    public function serializeXml(Writer $writer) {
+
+        $collations = [
+            'i;ascii-casemap',
+            'i;octet',
+            'i;unicode-casemap'
+        ];
 
-        throw new CannotSerialize('This element cannot be serialized.');
+        foreach($collations as $collation) {
+            $writer->writeElement('{' . Plugin::NS_CALDAV . '}supported-collation', $collation);
+        }
 
     }
 
@@ -70,19 +74,9 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
-
-        $self = new self();
-
-        $elems = $reader->parseInnerTree();
-
-        foreach($elems as $elem) {
-            if ($elem['name'] === '{DAV:}set') {
-                $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
-            }
-        }
+    static public function deserializeXml(Reader $reader) {
 
-        return $self;
+        throw new CannotDeserialize('This element does not have a deserializer');
 
     }
 
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/CalDAV/Xml/Request/CalendarMultiGetReport.php
similarity index 53%
copy from lib/DAV/Xml/Request/MkCol.php
copy to lib/CalDAV/Xml/Request/CalendarMultiGetReport.php
index d8d52652..48e196a 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/CalDAV/Xml/Request/CalendarMultiGetReport.php
@@ -1,32 +1,51 @@
 <?php
 
-namespace Sabre\DAV\Xml\Request;
+namespace Sabre\CalDAV\Xml\Request;
 
 use
     Sabre\Xml\Element,
     Sabre\Xml\Reader,
     Sabre\Xml\Writer,
-    Sabre\DAV\Exception\CannotSerialize;
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\CalDAV\Plugin;
 
 /**
- * WebDAV Extended MKCOL request parser.
+ * CalendarMultiGetReport request parser.
  *
- * This class parses the {DAV:}mkol request, as defined in:
+ * This class parses the {urn:ietf:params:xml:ns:caldav}calendar-multiget
+ * REPORT, as defined in:
  *
- * https://tools.ietf.org/html/rfc5689#section-5.1
+ * https://tools.ietf.org/html/rfc4791#section-7.9
  *
  * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class MkCol implements Element {
+class CalendarMultiGetReport implements Element {
 
     /**
-     * The list of properties that will be set.
+     * An array with requested properties.
      *
      * @var array
      */
-    public $properties = [];
+    public $properties;
+
+    /**
+     * This is an array with the urls that are being requested.
+     *
+     * @var array
+     */
+    public $hrefs;
+
+    /**
+     * If the calendar data must be expanded, this will contain an array with 2
+     * elements: start and end.
+     *
+     * Each may be a DateTime or null.
+     *
+     * @var array|null
+     */
+    public $expand = null;
 
     /**
      * The serialize method is called during xml writing.
@@ -43,7 +62,7 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    public function serializeXml(Writer $writer) {
 
         throw new CannotSerialize('This element cannot be serialized.');
 
@@ -70,19 +89,39 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
-
-        $self = new self();
+    static public function deserializeXml(Reader $reader) {
 
         $elems = $reader->parseInnerTree();
+        $hrefs = [];
+
+        $properties = null;
+
+        $expand = false;
 
         foreach($elems as $elem) {
-            if ($elem['name'] === '{DAV:}set') {
-                $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
+
+            switch($elem['name']) {
+
+                case '{DAV:}prop' :
+                    if (isset($elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data']['expand'])) {
+                        $expand = $elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data']['expand'];
+                    }
+                    $properties = array_keys($elem['value']);
+                    break;
+                case '{DAV:}href' :
+                    $hrefs[] = $elem['value'];
+                    break;
+
             }
+
         }
 
-        return $self;
+        $obj = new self();
+        $obj->properties = $properties;
+        $obj->hrefs = $hrefs;
+        $obj->expand = $expand;
+
+        return $obj;
 
     }
 
diff --git a/lib/CalDAV/Xml/Request/CalendarQueryReport.php b/lib/CalDAV/Xml/Request/CalendarQueryReport.php
new file mode 100644
index 0000000..1f97e35
--- /dev/null
+++ b/lib/CalDAV/Xml/Request/CalendarQueryReport.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Request;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\DAV\Exception\BadRequest,
+    Sabre\CalDAV\Plugin;
+
+/**
+ * CalendarQueryReport request parser.
+ *
+ * This class parses the {urn:ietf:params:xml:ns:caldav}calendar-query
+ * REPORT, as defined in:
+ *
+ * https://tools.ietf.org/html/rfc4791#section-7.9
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class CalendarQueryReport implements Element {
+
+    /**
+     * An array with requested properties.
+     *
+     * @var array
+     */
+    public $properties;
+
+    /**
+     * List of property/component filters.
+     *
+     * @var array
+     */
+    public $filter;
+
+    /**
+     * If the calendar data must be expanded, this will contain an array with 2
+     * elements: start and end.
+     *
+     * Each may be a DateTime or null.
+     *
+     * @var array|null
+     */
+    public $expand = null;
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        throw new CannotSerialize('This element cannot be serialized.');
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $elems = $reader->parseInnerTree();
+
+        $properties = null;
+        $expand = false;
+        $filter = null;
+
+        if (!is_array($elems)) $elems = [];
+
+        foreach($elems as $elem) {
+
+            switch($elem['name']) {
+
+                case '{DAV:}prop' :
+                    if (isset($elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data']['expand'])) {
+                        $expand = $elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data']['expand'];
+                    }
+                    $properties = array_keys($elem['value']);
+                    break;
+                case '{'.Plugin::NS_CALDAV.'}filter' :
+                    foreach($elem['value'] as $subElem) {
+                        if ($subElem['name'] === '{' . Plugin::NS_CALDAV . '}comp-filter') {
+                            if (!is_null($filter)) {
+                                throw new BadRequest('Only one top-level comp-filter may be defined');
+                            }
+                            $filter = $subElem['value'];
+                        }
+                    }
+                    break;
+
+            }
+
+        }
+
+        if (is_null($filter)) {
+            throw new BadRequest('The {' . Plugin::NS_CALDAV . '}filter element is required for this request');
+        }
+
+        $obj = new self();
+        $obj->properties = $properties;
+        $obj->filter = $filter;
+        $obj->expand = $expand;
+
+        return $obj;
+
+    }
+
+}
diff --git a/lib/CalDAV/Xml/Request/InviteReply.php b/lib/CalDAV/Xml/Request/InviteReply.php
new file mode 100644
index 0000000..9ee607a
--- /dev/null
+++ b/lib/CalDAV/Xml/Request/InviteReply.php
@@ -0,0 +1,175 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Request;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\Xml\Element\KeyValue,
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\DAV\Exception\BadRequest,
+    Sabre\CalDAV\Plugin,
+    Sabre\CalDAV\SharingPlugin;
+
+/**
+ * Invite-reply POST request parser
+ *
+ * This class parses the invite-reply POST request, as defined in:
+ *
+ * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class InviteReply implements Element {
+
+    /**
+     * The sharee calendar user address.
+     *
+     * This is the address that the original invite was set to
+     *
+     * @var string
+     */
+    public $href;
+
+    /**
+     * The uri to the calendar that was being shared.
+     *
+     * @var string
+     */
+    public $calendarUri;
+
+    /**
+     * The id of the invite message that's being responded to
+     *
+     * @var string
+     */
+    public $inReplyTo;
+
+    /**
+     * An optional message
+     *
+     * @var string
+     */
+    public $summary;
+
+    /**
+     * Either SharingPlugin::STATUS_ACCEPTED or SharingPlugin::STATUS_DECLINED.
+     *
+     * @var int
+     */
+    public $status;
+
+    /**
+     * Constructor
+     *
+     * @param string $href
+     * @param string $calendarUri
+     * @param string $inReplyTo
+     * @param string $summary
+     * @param int $status
+     */
+    public function __construct($href, $calendarUri, $inReplyTo, $summary, $status) {
+
+        $this->href = $href;
+        $this->calendarUri = $calendarUri;
+        $this->inReplyTo = $inReplyTo;
+        $this->summary = $summary;
+        $this->status = $status;
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        throw new CannotSerialize('This element cannot be serialized.');
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $elems = KeyValue::deserializeXml($reader);
+
+        $href = null;
+        $calendarUri = null;
+        $inReplyTo = null;
+        $summary = null;
+        $status = null;
+
+        foreach($elems as $name=>$value) {
+
+            switch($name) {
+
+                case '{' . Plugin::NS_CALENDARSERVER . '}hosturl' :
+                    foreach($value as $bla) {
+                        if ($bla['name'] === '{DAV:}href') {
+                            $calendarUri = $bla['value'];
+                        }
+                    }
+                    break;
+                case '{' . Plugin::NS_CALENDARSERVER . '}invite-accepted' :
+                    $status = SharingPlugin::STATUS_ACCEPTED;
+                    break;
+                case '{' . Plugin::NS_CALENDARSERVER . '}invite-declined' :
+                    $status = SharingPlugin::STATUS_DECLINED;
+                    break;
+                case '{' . Plugin::NS_CALENDARSERVER . '}in-reply-to' :
+                    $inReplyTo = $value;
+                    break;
+                case '{' . Plugin::NS_CALENDARSERVER . '}summary' :
+                    $summary = $value;
+                    break;
+                case '{DAV:}href' :
+                    $href = $value;
+                    break;
+                default :
+                    die('Death: ' . $name);
+            }
+
+        }
+        if (is_null($calendarUri)) {
+            throw new BadRequest('The {http://calendarserver.org/ns/}hosturl/{DAV:}href element must exist');
+        }
+
+        return new self($href, $calendarUri, $inReplyTo, $summary, $status);
+
+    }
+
+}
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/CalDAV/Xml/Request/MkCalendar.php
similarity index 74%
copy from lib/DAV/Xml/Request/MkCol.php
copy to lib/CalDAV/Xml/Request/MkCalendar.php
index d8d52652..b655267 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/CalDAV/Xml/Request/MkCalendar.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Sabre\DAV\Xml\Request;
+namespace Sabre\CalDAV\Xml\Request;
 
 use
     Sabre\Xml\Element,
@@ -9,17 +9,17 @@ use
     Sabre\DAV\Exception\CannotSerialize;
 
 /**
- * WebDAV Extended MKCOL request parser.
+ * MKCALENDAR parser.
  *
- * This class parses the {DAV:}mkol request, as defined in:
+ * This class parses the MKCALENDAR request, as defined in:
  *
- * https://tools.ietf.org/html/rfc5689#section-5.1
+ * https://tools.ietf.org/html/rfc4791#section-5.3.1
  *
- * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
  */
-class MkCol implements Element {
+class MkCalendar implements Element {
 
     /**
      * The list of properties that will be set.
@@ -29,6 +29,17 @@ class MkCol implements Element {
     public $properties = [];
 
     /**
+     * Returns the list of properties the calendar will be initialized with.
+     *
+     * @return array
+     */
+    function getProperties() {
+
+        return $this->properties;
+
+    }
+
+    /**
      * The serialize method is called during xml writing.
      *
      * It should use the $writer argument to encode this object into XML.
@@ -43,7 +54,7 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    function xmlSerialize(Writer $writer) {
 
         throw new CannotSerialize('This element cannot be serialized.');
 
@@ -70,7 +81,7 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static function xmlDeserialize(Reader $reader) {
 
         $self = new self();
 
diff --git a/lib/CalDAV/Xml/Request/Share.php b/lib/CalDAV/Xml/Request/Share.php
new file mode 100644
index 0000000..3d57a04
--- /dev/null
+++ b/lib/CalDAV/Xml/Request/Share.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace Sabre\CalDAV\Xml\Request;
+
+use
+    Sabre\Xml\Element,
+    Sabre\Xml\Reader,
+    Sabre\Xml\Writer,
+    Sabre\DAV\Exception\CannotSerialize,
+    Sabre\CalDAV\Plugin;
+
+/**
+ * Share POST request parser
+ *
+ * This class parses the share POST request, as defined in:
+ *
+ * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Share implements Element {
+
+    /**
+     * The list of new people added or updated.
+     *
+     * Every element has the following keys:
+     * 1. href - An email address
+     * 2. commonName - Some name
+     * 3. summary - An optional description of the share
+     * 4. readOnly - true or false
+     *
+     * @var array
+     */
+    public $set = [];
+
+    /**
+     * List of people removed from the share list.
+     *
+     * The list is a flat list of email addresses (including mailto:).
+     *
+     * @var array
+     */
+    public $remove = [];
+
+    /**
+     * Constructor
+     *
+     * @param array $set
+     * @param array $remove
+     */
+    public function __construct(array $set, array $remove) {
+
+        $this->set = $set;
+        $this->remove = $remove;
+
+    }
+
+    /**
+     * The serialize method is called during xml writing.
+     *
+     * It should use the $writer argument to encode this object into XML.
+     *
+     * Important note: it is not needed to create the parent element. The
+     * parent element is already created, and we only have to worry about
+     * attributes, child elements and text (if any).
+     *
+     * Important note 2: If you are writing any new elements, you are also
+     * responsible for closing them.
+     *
+     * @param Writer $writer
+     * @return void
+     */
+    public function serializeXml(Writer $writer) {
+
+        throw new CannotSerialize('This element cannot be serialized.');
+
+    }
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * Important note 2: You are responsible for advancing the reader to the
+     * next element. Not doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static public function deserializeXml(Reader $reader) {
+
+        $elems = $reader->parseInnerTree();
+
+        $set = [];
+
+        foreach($elems as $elem) {
+            switch($elem['name']) {
+
+                case '{'.Plugin::NS_CALENDARSERVER.'}set' :
+                    $sharee = $elem['value'];
+
+                    $sumElem = '{'.Plugin::NS_CALENDARSERVER.'}summary';
+
+                    $set[] = [
+                        'href'       => $sharee['{DAV:}href'],
+                        'commonName' => $sharee['{'.Plugin::NS_CALENDARSERVER.'}common-name'],
+                        'summary'    => isset($sharee[$sumElem])?$sharee[$sumElem]:null,
+                        'readOnly'   => isset($sharee['{' . Plugin::NS_CALENDARSERVER . '}readOnly']),
+                    ];
+                    break;
+
+                case '{'.Plugin::NS_CALENDARSERVER.'}remove' :
+                    $remove[] = $elem['value']['{DAV:}href'];
+                    break;
+
+            }
+        }
+
+        return new self($set, $remove);
+
+    }
+
+}
diff --git a/lib/DAV/Browser/Plugin.php b/lib/DAV/Browser/Plugin.php
index 9ca4ec0..e970d0c 100644
--- a/lib/DAV/Browser/Plugin.php
+++ b/lib/DAV/Browser/Plugin.php
@@ -631,7 +631,7 @@ HTML;
         $view = 'unknown';
         if (is_string($value)) {
             $view = 'string';
-        } elseif($value instanceof DAV\Property) {
+        } elseif($value instanceof \Sabre\Xml\XmlSerializable) {
 
             $mapping = [
                 'Sabre\\DAV\\Property\\IHref' => 'href',
diff --git a/lib/DAV/CorePlugin.php b/lib/DAV/CorePlugin.php
index 1fa69af..0618a84 100644
--- a/lib/DAV/CorePlugin.php
+++ b/lib/DAV/CorePlugin.php
@@ -561,21 +561,20 @@ class CorePlugin extends ServerPlugin {
 
             }
 
-            $dom = XMLUtil::loadDOMDocument($requestBody);
-            if (XMLUtil::toClarkNotation($dom->firstChild)!=='{DAV:}mkcol') {
+            try {
+                $mkcol = $this->server->xml->parse($requestBody);
+            } catch (\Sabre\Xml\ParseException $e) {
+                throw new Exception\BadRequest($e->getMessage(), null, $e);
+            }
+            if ($mkcol['name']!=='{DAV:}mkcol') {
 
                 // We must throw 415 for unsupported mkcol bodies
                 throw new Exception\UnsupportedMediaType('The request body for the MKCOL request must be a {DAV:}mkcol request construct.');
 
             }
 
-            $properties = [];
-            foreach($dom->firstChild->childNodes as $childNode) {
+            $properties = $mkcol['value']->getProperties();
 
-                if (XMLUtil::toClarkNotation($childNode)!=='{DAV:}set') continue;
-                $properties = array_merge($properties, XMLUtil::parseProperties($childNode, $this->server->propertyMap));
-
-            }
             if (!isset($properties['{DAV:}resourcetype']))
                 throw new Exception\BadRequest('The mkcol request must include a {DAV:}resourcetype property');
 
diff --git a/lib/DAV/Property/ResourceType.php b/lib/DAV/Property/ResourceType.php
deleted file mode 100644
index 55e9ed6..0000000
--- a/lib/DAV/Property/ResourceType.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-
-namespace Sabre\DAV\Property;
-
-use Sabre\DAV;
-
-/**
- * This class represents the {DAV:}resourcetype property
- *
- * Normally for files this is empty, and for collection {DAV:}collection.
- * However, other specs define different values for this.
- *
- * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/).
- * @author Evert Pot (http://evertpot.com/)
- * @license http://sabre.io/license/ Modified BSD License
- */
-class ResourceType extends DAV\Property {
-
-    /**
-     * resourceType
-     *
-     * @var array
-     */
-    public $resourceType = [];
-
-    /**
-     * __construct
-     *
-     * @param mixed $resourceType
-     */
-    function __construct($resourceType = []) {
-
-        if (is_array($resourceType))
-            $this->resourceType = $resourceType;
-        else
-            $this->resourceType = [$resourceType];
-
-    }
-
-    /**
-     * serialize
-     *
-     * @param DAV\Server $server
-     * @param \DOMElement $prop
-     * @return void
-     */
-    function serialize(DAV\Server $server, \DOMElement $prop) {
-
-        $propName = null;
-        $rt = $this->resourceType;
-
-        foreach($rt as $resourceType) {
-            if (preg_match('/^{([^}]*)}(.*)$/',$resourceType,$propName)) {
-
-                if (isset($server->xmlNamespaces[$propName[1]])) {
-                    $prop->appendChild($prop->ownerDocument->createElement($server->xmlNamespaces[$propName[1]] . ':' . $propName[2]));
-                } else {
-                    $prop->appendChild($prop->ownerDocument->createElementNS($propName[1],'custom:' . $propName[2]));
-                }
-
-            }
-        }
-
-    }
-
-    /**
-     * Returns the values in clark-notation
-     *
-     * For example ['{DAV:}collection']
-     *
-     * @return array
-     */
-    function getValue() {
-
-        return $this->resourceType;
-
-    }
-
-    /**
-     * Checks if the principal contains a certain value
-     *
-     * @param string $type
-     * @return bool
-     */
-    function is($type) {
-
-        return in_array($type, $this->resourceType);
-
-    }
-
-    /**
-     * Adds a resourcetype value to this property
-     *
-     * @param string $type
-     * @return void
-     */
-    function add($type) {
-
-        $this->resourceType[] = $type;
-        $this->resourceType = array_unique($this->resourceType);
-
-    }
-
-    /**
-     * Unserializes a DOM element into a ResourceType property.
-     *
-     * @param \DOMElement $dom
-     * @param array $propertyMap
-     * @return DAV\Property\ResourceType
-     */
-    static function unserialize(\DOMElement $dom, array $propertyMap) {
-
-        $value = [];
-        foreach($dom->childNodes as $child) {
-
-            $value[] = DAV\XMLUtil::toClarkNotation($child);
-
-        }
-
-        return new self($value);
-
-    }
-
-}
diff --git a/lib/DAV/Property/SupportedMethodSet.php b/lib/DAV/Property/SupportedMethodSet.php
deleted file mode 100644
index b0f6503..0000000
--- a/lib/DAV/Property/SupportedMethodSet.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-namespace Sabre\DAV\Property;
-
-use Sabre\DAV;
-
-/**
- * supported-method-set property.
- *
- * This property is defined in RFC3253.
- *
- * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/).
- * @author Evert Pot (http://evertpot.com/)
- * @license http://sabre.io/license/ Modified BSD License
- */
-class SupportedMethodSet extends DAV\Property {
-
-    /**
-     * List of methods
-     *
-     * @var string[]
-     */
-    protected $methods = [];
-
-    /**
-     * Creates the property
-     *
-     * Any reports passed in the constructor should be valid HTTP methods.
-     *
-     * @param string[] $methods
-     */
-    function __construct(array $method) {
-
-        $this->methods = $method;
-
-    }
-
-    /**
-     * Returns the list of supported methods.
-     *
-     * @return string[]
-     */
-    function getValue() {
-
-        return $this->methods;
-
-    }
-
-    /**
-     * Serializes the node
-     *
-     * @param DAV\Server $server
-     * @param \DOMElement $prop
-     * @return void
-     */
-    function serialize(DAV\Server $server, \DOMElement $prop) {
-
-        foreach($this->methods as $method) {
-
-            $supportedMethod = $prop->ownerDocument->createElement('d:supported-method');
-            $supportedMethod->setAttribute('name', $method);
-            $prop->appendChild($supportedMethod);
-
-        }
-
-    }
-
-}
diff --git a/lib/DAV/XMLUtil.php b/lib/DAV/XMLUtil.php
index af8b373..9401b07 100644
--- a/lib/DAV/XMLUtil.php
+++ b/lib/DAV/XMLUtil.php
@@ -23,9 +23,16 @@ class XMLUtil {
         '{DAV:}response'    => 'Sabre\\DAV\\Xml\\Element\\Response',
         '{DAV:}propstat'    => 'Sabre\\Xml\\Element\\KeyValue',
         '{DAV:}prop'        => 'Sabre\\Xml\\Element\\KeyValue',
+        '{DAV:}set'         => 'Sabre\\Xml\\Element\\KeyValue',
+        '{DAV:}remove'      => 'Sabre\\Xml\\Element\\KeyValue',
 
         // Requests
         '{DAV:}propfind' => 'Sabre\\DAV\\Xml\\Request\\PropFind',
+        '{DAV:}mkcol'    => 'Sabre\\DAV\\Xml\\Request\\MkCol',
+
+        // Properties
+        '{DAV:}resourcetype' => 'Sabre\\DAV\\Xml\\Property\\ResourceType',
+
     ];
 
     /**
diff --git a/lib/DAV/Xml/Property/ResourceType.php b/lib/DAV/Xml/Property/ResourceType.php
index bf12df7..1bbe928 100644
--- a/lib/DAV/Xml/Property/ResourceType.php
+++ b/lib/DAV/Xml/Property/ResourceType.php
@@ -13,11 +13,11 @@ use
  *
  * This class represents the {DAV:}resourcetype property, as defined in:
  *
- * https://tools.ietf.org/html/rfc4918#section-15.9 
+ * https://tools.ietf.org/html/rfc4918#section-15.9
  *
- * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
  */
 class ResourceType extends Element\Elements {
 
@@ -31,7 +31,7 @@ class ResourceType extends Element\Elements {
      *
      * @param array|string|null $resourceType
      */
-    public function __construct($resourceTypes = null) {
+    function __construct($resourceTypes = null) {
 
         if (is_null($resourceTypes)) {
             parent::__construct([]);
@@ -50,7 +50,7 @@ class ResourceType extends Element\Elements {
      *
      * @return array
      */
-    public function getValue() {
+    function getValue() {
 
         return $this->value;
 
@@ -62,7 +62,7 @@ class ResourceType extends Element\Elements {
      * @param string $type
      * @return bool
      */
-    public function is($type) {
+    function is($type) {
 
         return in_array($type, $this->value);
 
@@ -74,7 +74,7 @@ class ResourceType extends Element\Elements {
      * @param string $type
      * @return void
      */
-    public function add($type) {
+    function add($type) {
 
         $this->value[] = $type;
         $this->value = array_unique($this->value);
@@ -102,10 +102,10 @@ class ResourceType extends Element\Elements {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static function xmlDeserialize(Reader $reader) {
 
         return
-            new self(parent::deserializeXml($reader));
+            new self(parent::xmlDeserialize($reader));
 
     }
 
diff --git a/lib/DAV/Xml/Property/SupportedLock.php b/lib/DAV/Xml/Property/SupportedLock.php
index 979442c..ce0593e 100644
--- a/lib/DAV/Xml/Property/SupportedLock.php
+++ b/lib/DAV/Xml/Property/SupportedLock.php
@@ -61,12 +61,12 @@ class SupportedLock implements Element {
         if (!$this->supportsLocks) return null;
 
         $writer->writeElement('{DAV:}lockentry', [
-            '{DAV:}lockscope' => ['{DAV:}exclusive' => null],        
-            '{DAV:}locktype' =>  ['{DAV:}write' => null],        
+            '{DAV:}lockscope' => ['{DAV:}exclusive' => null],
+            '{DAV:}locktype' =>  ['{DAV:}write' => null],
         ]);
         $writer->writeElement('{DAV:}lockentry', [
-            '{DAV:}lockscope' => ['{DAV:}shared' => null],        
-            '{DAV:}locktype' =>  ['{DAV:}write' => null],        
+            '{DAV:}lockscope' => ['{DAV:}shared' => null],
+            '{DAV:}locktype' =>  ['{DAV:}write' => null],
         ]);
 
     }
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/DAV/Xml/Request/MkCol.php
index d8d52652..3943c7b 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/DAV/Xml/Request/MkCol.php
@@ -15,9 +15,9 @@ use
  *
  * https://tools.ietf.org/html/rfc5689#section-5.1
  *
- * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
  */
 class MkCol implements Element {
 
@@ -26,7 +26,19 @@ class MkCol implements Element {
      *
      * @var array
      */
-    public $properties = [];
+    protected $properties = [];
+
+    /**
+     * Returns a key=>value array with properties that are supposed to get set
+     * during creation of the new collection.
+     *
+     * @return array
+     */
+    function getProperties() {
+
+        return $this->properties;
+
+    }
 
     /**
      * The serialize method is called during xml writing.
@@ -43,7 +55,7 @@ class MkCol implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    function xmlSerialize(Writer $writer) {
 
         throw new CannotSerialize('This element cannot be serialized.');
 
@@ -70,7 +82,7 @@ class MkCol implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static function xmlDeserialize(Reader $reader) {
 
         $self = new self();
 
diff --git a/lib/DAV/Xml/Response/MultiStatus.php b/lib/DAV/Xml/Response/MultiStatus.php
index bba5784..cf4b5d1 100644
--- a/lib/DAV/Xml/Response/MultiStatus.php
+++ b/lib/DAV/Xml/Response/MultiStatus.php
@@ -17,9 +17,9 @@ use
  * And it also adds the {DAV:}synctoken change from:
  * http://tools.ietf.org/html/rfc6578#section-6.4
  *
- * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
  */
 class MultiStatus implements Element {
 
@@ -42,7 +42,7 @@ class MultiStatus implements Element {
      *
      * @param \Sabre\DAV\Xml\Element\Response[] $responses
      */
-    public function __construct(array $responses, $syncToken = null) {
+    function __construct(array $responses, $syncToken = null) {
 
         $this->responses = $responses;
         $this->syncToken = $syncToken;
@@ -54,7 +54,7 @@ class MultiStatus implements Element {
      *
      * @return \Sabre\DAV\Xml\Element\Response[]
      */
-    public function getResponses() {
+    function getResponses() {
 
         return $this->responses;
 
@@ -65,7 +65,7 @@ class MultiStatus implements Element {
      *
      * @return string|null
      */
-    public function getSyncToken() {
+    function getSyncToken() {
 
         return $this->syncToken;
 
@@ -86,7 +86,7 @@ class MultiStatus implements Element {
      * @param Writer $writer
      * @return void
      */
-    public function xmlSerialize(Writer $writer) {
+    function xmlSerialize(Writer $writer) {
 
         foreach($this->getResponses() as $response) {
             $writer->writeElement('{DAV:}response', $response);
@@ -118,7 +118,7 @@ class MultiStatus implements Element {
      * @param Reader $reader
      * @return mixed
      */
-    static public function xmlDeserialize(Reader $reader) {
+    static function xmlDeserialize(Reader $reader) {
 
         $elements = $reader->parseInnerTree();
 
diff --git a/tests/Sabre/CalDAV/PluginTest.php b/tests/Sabre/CalDAV/PluginTest.php
index a6e9291..415ba31 100644
--- a/tests/Sabre/CalDAV/PluginTest.php
+++ b/tests/Sabre/CalDAV/PluginTest.php
@@ -376,7 +376,7 @@ END:VCALENDAR';
 
         }
         $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
-        $this->assertTrue($newCalendar[$sccs] instanceof Property\SupportedCalendarComponentSet);
+        $this->assertTrue($newCalendar[$sccs] instanceof Xml\Property\SupportedCalendarComponentSet);
         $this->assertEquals(array('VEVENT'),$newCalendar[$sccs]->getValue());
 
     }
diff --git a/tests/Sabre/CalDAV/SharingPluginTest.php b/tests/Sabre/CalDAV/SharingPluginTest.php
index b6f2f8e..c865ac6 100644
--- a/tests/Sabre/CalDAV/SharingPluginTest.php
+++ b/tests/Sabre/CalDAV/SharingPluginTest.php
@@ -92,12 +92,12 @@ class SharingPluginTest extends \Sabre\DAVServerTest {
             array()
         );
         $result = $this->server->updateProperties('calendars/user1/cal1', array(
-            '{DAV:}resourcetype' => new DAV\Property\ResourceType(array('{DAV:}collection'))
+            '{DAV:}resourcetype' => new DAV\Xml\Property\ResourceType(['{DAV:}collection'])
         ));
 
-        $this->assertEquals(array(
+        $this->assertEquals([
             '{DAV:}resourcetype' => 200
-        ), $result);
+        ], $result);
 
         $this->assertEquals(0, count($this->caldavBackend->getShares(1)));
 
diff --git a/tests/Sabre/DAV/Property/ResourceTypeTest.php b/tests/Sabre/DAV/Property/ResourceTypeTest.php
deleted file mode 100644
index 1063b52..0000000
--- a/tests/Sabre/DAV/Property/ResourceTypeTest.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-
-namespace Sabre\DAV\Property;
-
-use Sabre\DAV;
-
-class ResourceTypeTest extends \PHPUnit_Framework_TestCase {
-
-    function testConstruct() {
-
-        $resourceType = new ResourceType(array('{DAV:}collection'));
-        $this->assertEquals(array('{DAV:}collection'),$resourceType->getValue());
-
-        $resourceType = new ResourceType('{DAV:}principal');
-        $this->assertEquals(array('{DAV:}principal'),$resourceType->getValue());
-
-    }
-
-    /**
-     * @depends testConstruct
-     */
-    function testSerialize() {
-
-        $resourceType = new ResourceType(array('{DAV:}collection','{DAV:}principal'));
-
-        $doc = new \DOMDocument();
-        $root = $doc->createElement('d:anything');
-        $root->setAttribute('xmlns:d','DAV:');
-
-        $doc->appendChild($root);
-        $server = new DAV\Server();
-        $resourceType->serialize($server, $root);
-
-        $xml = $doc->saveXML();
-
-        $this->assertEquals(
-'<?xml version="1.0"?>
-<d:anything xmlns:d="DAV:"><d:collection/><d:principal/></d:anything>
-', $xml);
-
-    }
-
-    /**
-     * @depends testSerialize
-     */
-    function testSerializeCustomNS() {
-
-        $resourceType = new ResourceType(array('{http://example.org/NS}article'));
-
-        $doc = new \DOMDocument();
-        $root = $doc->createElement('d:anything');
-        $root->setAttribute('xmlns:d','DAV:');
-
-        $doc->appendChild($root);
-        $server = new DAV\Server();
-        $resourceType->serialize($server, $root);
-
-        $xml = $doc->saveXML();
-
-        $this->assertEquals(
-'<?xml version="1.0"?>
-<d:anything xmlns:d="DAV:"><custom:article xmlns:custom="http://example.org/NS"/></d:anything>
-', $xml);
-
-    }
-
-    /**
-     * @depends testConstruct
-     */
-    function testIs() {
-
-        $resourceType = new ResourceType(array('{DAV:}collection','{DAV:}principal'));
-        $this->assertTrue($resourceType->is('{DAV:}collection'));
-        $this->assertFalse($resourceType->is('{DAV:}blabla'));
-
-    }
-
-    /**
-     * @depends testConstruct
-     */
-    function testAdd() {
-
-        $resourceType = new ResourceType(array('{DAV:}collection','{DAV:}principal'));
-        $resourceType->add('{DAV:}foo');
-        $this->assertEquals(array('{DAV:}collection','{DAV:}principal','{DAV:}foo'), $resourceType->getValue());
-
-    }
-
-    /**
-     * @depends testConstruct
-     */
-    function testUnserialize() {
-
-        $xml ='<?xml version="1.0"?>
-<d:anything xmlns:d="DAV:"><d:collection/><d:principal/></d:anything>
-';
-
-        $dom = DAV\XMLUtil::loadDOMDocument($xml);
-
-        $resourceType = ResourceType::unserialize($dom->firstChild, array());
-        $this->assertEquals(array('{DAV:}collection','{DAV:}principal'),$resourceType->getValue());
-
-    }
-
-}
diff --git a/tests/Sabre/DAV/ServerMKCOLTest.php b/tests/Sabre/DAV/ServerMKCOLTest.php
index 5c04d6f..9580f97 100644
--- a/tests/Sabre/DAV/ServerMKCOLTest.php
+++ b/tests/Sabre/DAV/ServerMKCOLTest.php
@@ -74,7 +74,7 @@ class ServerMKCOLTest extends AbstractServer {
             'Content-Type' => ['application/xml; charset=utf-8'],
         ),$this->response->getHeaders());
 
-        $this->assertEquals(400, $this->response->status);
+        $this->assertEquals(400, $this->response->getStatus(), $this->response->getBodyAsString() );
 
     }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/php-sabredav.git



More information about the Pkg-owncloud-commits mailing list