예제 #1
0
파일: taglist.php 프로젝트: nem0xff/core
 /**
  * Unserializes this property from a DOM Element
  *
  * This method returns an instance of this class.
  * It will only decode tag values.
  *
  * @param \DOMElement $dom
  * @param array $propertyMap
  * @return \OCA\DAV\Connector\Sabre\TagList
  */
 static function unserialize(\DOMElement $dom, array $propertyMap)
 {
     $tags = array();
     foreach ($dom->childNodes as $child) {
         if (DAV\XMLUtil::toClarkNotation($child) === '{' . self::NS_OWNCLOUD . '}tag') {
             $tags[] = $child->textContent;
         }
     }
     return new self($tags);
 }
예제 #2
0
 /**
  * Unserializes this property from a DOM Element
  *
  * This method returns an instance of this class.
  * It will only decode {DAV:}href values.
  *
  * @param \DOMElement $dom
  * @param array $propertyMap
  * @return DAV\Property\HrefList
  */
 static function unserialize(\DOMElement $dom, array $propertyMap)
 {
     $hrefs = [];
     foreach ($dom->childNodes as $child) {
         if (DAV\XMLUtil::toClarkNotation($child) === '{DAV:}href') {
             $hrefs[] = $child->textContent;
         }
     }
     return new self($hrefs, false);
 }
 /**
  * Unserializes the DOMElement back into a Property class.
  *
  * @param \DOMElement $node
  * @return Property_SupportedCalendarComponentSet
  */
 static function unserialize(\DOMElement $node)
 {
     $components = array();
     foreach ($node->childNodes as $childNode) {
         if (DAV\XMLUtil::toClarkNotation($childNode) === '{' . CalDAV\Plugin::NS_CALDAV . '}comp') {
             $components[] = $childNode->getAttribute('name');
         }
     }
     return new self($components);
 }
 /**
  * Unserializes the DOMElement back into a Property class.
  *
  * @param \DOMElement $node
  * @param array $propertyMap
  * @return ScheduleCalendarTransp
  */
 static function unserialize(\DOMElement $node, array $propertyMap)
 {
     $value = null;
     foreach ($node->childNodes as $childNode) {
         switch (DAV\XMLUtil::toClarkNotation($childNode)) {
             case '{' . CalDAV\Plugin::NS_CALDAV . '}opaque':
                 $value = self::OPAQUE;
                 break;
             case '{' . CalDAV\Plugin::NS_CALDAV . '}transparent':
                 $value = self::TRANSPARENT;
                 break;
         }
     }
     if (is_null($value)) {
         return null;
     }
     return new self($value);
 }
예제 #5
0
 /**
  * Unserializes a DOM element into a ResourceType property.
  *
  * @param \DOMElement $dom
  * @return DAV\Property\ResourceType
  */
 public static function unserialize(\DOMElement $dom)
 {
     $value = array();
     foreach ($dom->childNodes as $child) {
         $value[] = DAV\XMLUtil::toClarkNotation($child);
     }
     return new self($value);
 }
예제 #6
0
 /**
  * HTTP REPORT method implementation
  *
  * Although the REPORT method is not part of the standard WebDAV spec (it's from rfc3253)
  * It's used in a lot of extensions, so it made sense to implement it into the core.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpReport(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     $body = $request->getBodyAsString();
     $dom = XMLUtil::loadDOMDocument($body);
     $reportName = XMLUtil::toClarkNotation($dom->firstChild);
     if ($this->server->emit('report', [$reportName, $dom, $path])) {
         // If emit returned true, it means the report was not supported
         throw new Exception\ReportNotSupported();
     }
     // Sending back false will interupt the event chain and tell the server
     // we've handled this method.
     return false;
 }
예제 #7
0
 /**
  * Deserializes a DOM element into a property object.
  *
  * @param \DOMElement $dom
  * @return Principal
  */
 public static function unserialize(\DOMElement $dom)
 {
     $parent = $dom->firstChild;
     while (!DAV\XMLUtil::toClarkNotation($parent)) {
         $parent = $parent->nextSibling;
     }
     switch (DAV\XMLUtil::toClarkNotation($parent)) {
         case '{DAV:}unauthenticated':
             return new self(self::UNAUTHENTICATED);
         case '{DAV:}authenticated':
             return new self(self::AUTHENTICATED);
         case '{DAV:}href':
             return new self(self::HREF, $parent->textContent);
         case '{DAV:}all':
             return new self(self::ALL);
         default:
             throw new DAV\Exception\BadRequest('Unexpected element (' . DAV\XMLUtil::toClarkNotation($parent) . '). Could not deserialize');
     }
 }
예제 #8
0
 /**
  * Unserializes the {DAV:}current-user-privilege-set element.
  *
  * @param \DOMElement $node
  * @param array $propertyMap
  * @return CurrentUserPrivilegeSet
  */
 static function unserialize(\DOMElement $node, array $propertyMap)
 {
     $result = [];
     $xprivs = $node->getElementsByTagNameNS('urn:DAV', 'privilege');
     for ($jj = 0; $jj < $xprivs->length; $jj++) {
         $xpriv = $xprivs->item($jj);
         $privilegeName = null;
         for ($kk = 0; $kk < $xpriv->childNodes->length; $kk++) {
             $childNode = $xpriv->childNodes->item($kk);
             if ($t = DAV\XMLUtil::toClarkNotation($childNode)) {
                 $privilegeName = $t;
                 break;
             }
         }
         $result[] = $privilegeName;
     }
     return new self($result);
 }
예제 #9
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param \DOMNode $dom
  * @return void
  */
 protected function freeBusyQueryReport(\DOMNode $dom)
 {
     $start = null;
     $end = null;
     foreach ($dom->firstChild->childNodes as $childNode) {
         $clark = DAV\XMLUtil::toClarkNotation($childNode);
         if ($clark == '{' . self::NS_CALDAV . '}time-range') {
             $start = $childNode->getAttribute('start');
             $end = $childNode->getAttribute('end');
             break;
         }
     }
     if ($start) {
         $start = VObject\DateTimeParser::parseDateTime($start);
     }
     if ($end) {
         $end = VObject\DateTimeParser::parseDateTime($end);
     }
     if (!$start && !$end) {
         throw new DAV\Exception\BadRequest('The freebusy report must have a time-range filter');
     }
     $acl = $this->server->getPlugin('acl');
     if (!$acl) {
         throw new DAV\Exception('The ACL plugin must be loaded for free-busy queries to work');
     }
     $uri = $this->server->getRequestUri();
     $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof ICalendar) {
         throw new DAV\Exception\NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     // Doing a calendar-query first, to make sure we get the most
     // performance.
     $urls = $calendar->calendarQuery(array('name' => 'VCALENDAR', 'comp-filters' => array(array('name' => 'VEVENT', 'comp-filters' => array(), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => array('start' => $start, 'end' => $end))), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => null));
     $objects = array_map(function ($url) use($calendar) {
         $obj = $calendar->getChild($url)->get();
         return $obj;
     }, $urls);
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->sendStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->sendBody($result);
 }
예제 #10
0
 /**
  * This method parses a PropPatch request
  *
  * PropPatch changes the properties for a resource. This method
  * returns a list of properties.
  *
  * The keys in the returned array contain the property name (e.g.: {DAV:}displayname,
  * and the value contains the property value. If a property is to be removed the value
  * will be null.
  *
  * @param string $body xml body
  * @return array list of properties in need of updating or deletion
  */
 function parsePropPatchRequest($body)
 {
     //We'll need to change the DAV namespace declaration to something else in order to make it parsable
     $dom = XMLUtil::loadDOMDocument($body);
     $newProperties = [];
     foreach ($dom->firstChild->childNodes as $child) {
         if ($child->nodeType !== XML_ELEMENT_NODE) {
             continue;
         }
         $operation = XMLUtil::toClarkNotation($child);
         if ($operation !== '{DAV:}set' && $operation !== '{DAV:}remove') {
             continue;
         }
         $innerProperties = XMLUtil::parseProperties($child, $this->propertyMap);
         foreach ($innerProperties as $propertyName => $propertyValue) {
             if ($operation === '{DAV:}remove') {
                 $propertyValue = null;
             }
             $newProperties[$propertyName] = $propertyValue;
         }
     }
     return $newProperties;
 }
예제 #11
0
 /**
  * Unserializes the {DAV:}acl xml element.
  *
  * @param \DOMElement $dom
  * @param array $propertyMap
  * @return Acl
  */
 static function unserialize(\DOMElement $dom, array $propertyMap)
 {
     $privileges = [];
     $xaces = $dom->getElementsByTagNameNS('urn:DAV', 'ace');
     for ($ii = 0; $ii < $xaces->length; $ii++) {
         $xace = $xaces->item($ii);
         $principal = $xace->getElementsByTagNameNS('urn:DAV', 'principal');
         if ($principal->length !== 1) {
             throw new DAV\Exception\BadRequest('Each {DAV:}ace element must have one {DAV:}principal element');
         }
         $principal = Principal::unserialize($principal->item(0), $propertyMap);
         switch ($principal->getType()) {
             case Principal::HREF:
                 $principal = $principal->getHref();
                 break;
             case Principal::AUTHENTICATED:
                 $principal = '{DAV:}authenticated';
                 break;
             case Principal::UNAUTHENTICATED:
                 $principal = '{DAV:}unauthenticated';
                 break;
             case Principal::ALL:
                 $principal = '{DAV:}all';
                 break;
         }
         $protected = false;
         if ($xace->getElementsByTagNameNS('urn:DAV', 'protected')->length > 0) {
             $protected = true;
         }
         $grants = $xace->getElementsByTagNameNS('urn:DAV', 'grant');
         if ($grants->length < 1) {
             throw new DAV\Exception\NotImplemented('Every {DAV:}ace element must have a {DAV:}grant element. {DAV:}deny is not yet supported');
         }
         $grant = $grants->item(0);
         $xprivs = $grant->getElementsByTagNameNS('urn:DAV', 'privilege');
         for ($jj = 0; $jj < $xprivs->length; $jj++) {
             $xpriv = $xprivs->item($jj);
             $privilegeName = null;
             for ($kk = 0; $kk < $xpriv->childNodes->length; $kk++) {
                 $childNode = $xpriv->childNodes->item($kk);
                 if ($t = DAV\XMLUtil::toClarkNotation($childNode)) {
                     $privilegeName = $t;
                     break;
                 }
             }
             if (is_null($privilegeName)) {
                 throw new DAV\Exception\BadRequest('{DAV:}privilege elements must have a privilege element contained within them.');
             }
             $privileges[] = ['principal' => $principal, 'protected' => $protected, 'privilege' => $privilegeName];
         }
     }
     return new self($privileges);
 }
예제 #12
0
 /**
  * This event is triggered when the server didn't know how to handle a
  * certain request.
  *
  * We intercept this to handle POST requests on calendars.
  *
  * @param string $method
  * @param string $uri
  * @return null|bool
  */
 public function unknownMethod($method, $uri)
 {
     if ($method !== 'POST') {
         return;
     }
     // Only handling xml
     $contentType = $this->server->httpRequest->getHeader('Content-Type');
     if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
         return;
     }
     // Making sure the node exists
     try {
         $node = $this->server->tree->getNodeForPath($uri);
     } catch (DAV\Exception\NotFound $e) {
         return;
     }
     $requestBody = $this->server->httpRequest->getBody(true);
     // If this request handler could not deal with this POST request, it
     // will return 'null' and other plugins get a chance to handle the
     // request.
     //
     // However, we already requested the full body. This is a problem,
     // because a body can only be read once. This is why we preemptively
     // re-populated the request body with the existing data.
     $this->server->httpRequest->setBody($requestBody);
     $dom = DAV\XMLUtil::loadDOMDocument($requestBody);
     $documentType = DAV\XMLUtil::toClarkNotation($dom->firstChild);
     switch ($documentType) {
         // Dealing with the 'share' document, which modified invitees on a
         // calendar.
         case '{' . Plugin::NS_CALENDARSERVER . '}share':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableCalendar) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $mutations = $this->parseShareRequest($dom);
             $node->updateShares($mutations[0], $mutations[1]);
             $this->server->httpResponse->sendStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
             // The invite-reply document is sent when the user replies to an
             // invitation of a calendar share.
         // The invite-reply document is sent when the user replies to an
         // invitation of a calendar share.
         case '{' . Plugin::NS_CALENDARSERVER . '}invite-reply':
             // This only works on the calendar-home-root node.
             if (!$node instanceof UserCalendars) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $message = $this->parseInviteReplyRequest($dom);
             $url = $node->shareReply($message['href'], $message['status'], $message['calendarUri'], $message['inReplyTo'], $message['summary']);
             $this->server->httpResponse->sendStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             if ($url) {
                 $dom = new \DOMDocument('1.0', 'UTF-8');
                 $dom->formatOutput = true;
                 $root = $dom->createElement('cs:shared-as');
                 foreach ($this->server->xmlNamespaces as $namespace => $prefix) {
                     $root->setAttribute('xmlns:' . $prefix, $namespace);
                 }
                 $dom->appendChild($root);
                 $href = new DAV\Property\Href($url);
                 $href->serialize($this->server, $root);
                 $this->server->httpResponse->setHeader('Content-Type', 'application/xml');
                 $this->server->httpResponse->sendBody($dom->saveXML());
             }
             // Breaking the event chain
             return false;
         case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableCalendar) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $node->setPublishStatus(true);
             // iCloud sends back the 202, so we will too.
             $this->server->httpResponse->sendStatus(202);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
         case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableCalendar) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $node->setPublishStatus(false);
             $this->server->httpResponse->sendStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
     }
 }
예제 #13
0
 /**
  * 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);
 }
예제 #14
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param \DOMNode $dom
  * @return void
  */
 protected function freeBusyQueryReport(\DOMNode $dom)
 {
     $start = null;
     $end = null;
     foreach ($dom->firstChild->childNodes as $childNode) {
         $clark = DAV\XMLUtil::toClarkNotation($childNode);
         if ($clark == '{' . self::NS_CALDAV . '}time-range') {
             $start = $childNode->getAttribute('start');
             $end = $childNode->getAttribute('end');
             break;
         }
     }
     if ($start) {
         $start = VObject\DateTimeParser::parseDateTime($start);
     }
     if ($end) {
         $end = VObject\DateTimeParser::parseDateTime($end);
     }
     $uri = $this->server->getRequestUri();
     if (!$start && !$end) {
         throw new DAV\Exception\BadRequest('The freebusy report must have a time-range filter');
     }
     $acl = $this->server->getPlugin('acl');
     if ($acl) {
         $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     }
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof ICalendar) {
         throw new DAV\Exception\NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     $tzProp = '{' . self::NS_CALDAV . '}calendar-timezone';
     // Figuring out the default timezone for the calendar, for floating
     // times.
     $calendarProps = $this->server->getProperties($uri, [$tzProp]);
     if (isset($calendarProps[$tzProp])) {
         $vtimezoneObj = VObject\Reader::read($calendarProps[$tzProp]);
         $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone();
     } else {
         $calendarTimeZone = new DateTimeZone('UTC');
     }
     // Doing a calendar-query first, to make sure we get the most
     // performance.
     $urls = $calendar->calendarQuery(['name' => 'VCALENDAR', 'comp-filters' => [['name' => 'VEVENT', 'comp-filters' => [], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => ['start' => $start, 'end' => $end]]], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => null]);
     $objects = array_map(function ($url) use($calendar) {
         $obj = $calendar->getChild($url)->get();
         return $obj;
     }, $urls);
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $generator->setTimeZone($calendarTimeZone);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->setStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->setBody($result);
 }
 /**
  * This function handles support for the POST method
  *
  * @param  string  $method
  * @param  string  $uri
  * @return bool
  */
 public function unknownMethod($method, $uri)
 {
     switch ($method) {
         case 'POST':
             $body = $this->server->httpRequest->getBody(true);
             try {
                 $dom = \Sabre\DAV\XMLUtil::loadDOMDocument($body);
             } catch (\Sabre\DAV\Exception\BadRequest $sdavebr) {
                 return;
             }
             $reportName = \Sabre\DAV\XMLUtil::toClarkNotation($dom->firstChild);
             switch ($reportName) {
                 case '{' . self::NS_INVERSE . '}acl-query':
                     $this->aclQueryPost($dom, $uri);
                     return false;
             }
     }
 }
예제 #16
0
 /**
  * Unserializes this property from a DOM Element
  *
  * This method returns an instance of this class.
  * It will only decode {DAV:}href values. For non-compatible elements null will be returned.
  *
  * @param \DOMElement $dom
  * @param array $propertyMap
  * @return DAV\Property\Href
  */
 static function unserialize(\DOMElement $dom, array $propertyMap)
 {
     if ($dom->firstChild && DAV\XMLUtil::toClarkNotation($dom->firstChild) === '{DAV:}href') {
         return new self($dom->firstChild->textContent, false);
     }
 }
예제 #17
0
 /**
  * parsePrincipalPropertySearchReportRequest
  *
  * This method parses the request body from a
  * {DAV:}principal-property-search report.
  *
  * This method returns an array with two elements:
  *  1. an array with properties to search on, and their values
  *  2. a list of propertyvalues that should be returned for the request.
  *
  * @param \DOMDocument $dom
  * @return array
  */
 protected function parsePrincipalPropertySearchReportRequest($dom)
 {
     $httpDepth = $this->server->getHTTPDepth(0);
     if ($httpDepth !== 0) {
         throw new DAV\Exception\BadRequest('This report is only defined when Depth: 0');
     }
     $searchProperties = [];
     $applyToPrincipalCollectionSet = false;
     $test = $dom->firstChild->getAttribute('test') === 'anyof' ? 'anyof' : 'allof';
     // Parsing the search request
     foreach ($dom->firstChild->childNodes as $searchNode) {
         if (DAV\XMLUtil::toClarkNotation($searchNode) == '{DAV:}apply-to-principal-collection-set') {
             $applyToPrincipalCollectionSet = true;
         }
         if (DAV\XMLUtil::toClarkNotation($searchNode) !== '{DAV:}property-search') {
             continue;
         }
         $propertyName = null;
         $propertyValue = null;
         foreach ($searchNode->childNodes as $childNode) {
             switch (DAV\XMLUtil::toClarkNotation($childNode)) {
                 case '{DAV:}prop':
                     $property = DAV\XMLUtil::parseProperties($searchNode);
                     reset($property);
                     $propertyName = key($property);
                     break;
                 case '{DAV:}match':
                     $propertyValue = $childNode->textContent;
                     break;
             }
         }
         if (is_null($propertyName) || is_null($propertyValue)) {
             throw new DAV\Exception\BadRequest('Invalid search request. propertyname: ' . $propertyName . '. propertvvalue: ' . $propertyValue);
         }
         $searchProperties[$propertyName] = $propertyValue;
     }
     return [$searchProperties, array_keys(DAV\XMLUtil::parseProperties($dom->firstChild)), $applyToPrincipalCollectionSet, $test];
 }
예제 #18
0
 /**
  * We intercept this to handle POST requests on calendars.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return null|bool
  */
 function httpPost(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     // Only handling xml
     $contentType = $request->getHeader('Content-Type');
     if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
         return;
     }
     // Making sure the node exists
     try {
         $node = $this->server->tree->getNodeForPath($path);
     } catch (NotFound $e) {
         return;
     }
     // CSRF protection
     $this->protectAgainstCSRF();
     $requestBody = $request->getBodyAsString();
     // If this request handler could not deal with this POST request, it
     // will return 'null' and other plugins get a chance to handle the
     // request.
     //
     // However, we already requested the full body. This is a problem,
     // because a body can only be read once. This is why we preemptively
     // re-populated the request body with the existing data.
     $request->setBody($requestBody);
     $dom = XMLUtil::loadDOMDocument($requestBody);
     $documentType = XMLUtil::toClarkNotation($dom->firstChild);
     switch ($documentType) {
         // Dealing with the 'share' document, which modified invitees on a
         // calendar.
         case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableAddressBook) {
                 return;
             }
             $this->server->transactionType = 'post-calendar-share';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $mutations = $this->parseShareRequest($dom);
             $node->updateShares($mutations[0], $mutations[1]);
             $response->setStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $response->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
     }
 }