Ejemplo n.º 1
0
    /**
     * @depends testSimple
     */
    function testUnserializerBadData()
    {
        $xml = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:" xmlns:cal="' . CalDAV\Plugin::NS_CALDAV . '">' . '<cal:foo/>' . '</d:root>';
        $dom = DAV\XMLUtil::loadDOMDocument($xml);
        $this->assertNull(ScheduleCalendarTransp::unserialize($dom->firstChild));
    }
    function testSerialize()
    {
        $dt = new \DateTime('2010-03-14 16:35', new \DateTimeZone('UTC'));
        $lastMod = new GetLastModified($dt);
        $doc = new \DOMDocument();
        $root = $doc->createElement('d:getlastmodified');
        $root->setAttribute('xmlns:d', 'DAV:');
        $doc->appendChild($root);
        $server = new DAV\Server();
        $lastMod->serialize($server, $root);
        $xml = $doc->saveXML();
        /*
        $this->assertEquals(
        '<?xml version="1.0"?>
        <d:getlastmodified xmlns:d="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">' .
        HTTP\Util::toHTTPDate($dt) .
        '</d:getlastmodified>
        ', $xml);
        */
        $this->assertEquals('<?xml version="1.0"?>
<d:getlastmodified xmlns:d="DAV:">' . HTTP\Util::toHTTPDate($dt) . '</d:getlastmodified>
', $xml);
        $ok = false;
        try {
            GetLastModified::unserialize(DAV\XMLUtil::loadDOMDocument($xml)->firstChild, array());
        } catch (DAV\Exception $e) {
            $ok = true;
        }
        if (!$ok) {
            $this->markTestFailed('Unserialize should not be supported');
        }
    }
Ejemplo n.º 3
0
 function parse($xml)
 {
     $xml = implode("\n", $xml);
     $dom = DAV\XMLUtil::loadDOMDocument($xml);
     $q = new AddressBookQueryParser($dom);
     $q->parse();
     return $q;
 }
    /**
     * @depends testSimple
     */
    function testUnserializer()
    {
        $xml = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:" xmlns:cal="' . \Sabre\CalDAV\Plugin::NS_CALDAV . '">' . '<cal:comp name="VEVENT"/>' . '<cal:comp name="VJOURNAL"/>' . '</d:root>';
        $dom = \Sabre\DAV\XMLUtil::loadDOMDocument($xml);
        $property = SupportedCalendarComponentSet::unserialize($dom->firstChild);
        $this->assertTrue($property instanceof SupportedCalendarComponentSet);
        $this->assertEquals(array('VEVENT', 'VJOURNAL'), $property->getValue());
    }
Ejemplo n.º 5
0
    /**
     * @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());
    }
    function testUnserialize()
    {
        $source = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:">
    <d:privilege>
        <d:write-properties />
    </d:privilege>
    <d:privilege>
        <d:read />
    </d:privilege>
</d:root>
';
        $dom = DAV\XMLUtil::loadDOMDocument($source);
        $result = CurrentUserPrivilegeSet::unserialize($dom->firstChild, array());
        $this->assertTrue($result->has('{DAV:}read'));
        $this->assertTrue($result->has('{DAV:}write-properties'));
        $this->assertFalse($result->has('{DAV:}bind'));
    }
Ejemplo n.º 7
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;
     }
 }
Ejemplo n.º 8
0
    public function testSubsequentSyncSyncCollectionDepthFallBack()
    {
        // Making a change
        $this->collection->addChange(['file1.txt'], [], []);
        // Making another change
        $this->collection->addChange([], ['file2.txt'], ['file3.txt']);
        $request = HTTP\Sapi::createFromServerArray(['REQUEST_METHOD' => 'REPORT', 'REQUEST_URI' => '/coll/', 'CONTENT_TYPE' => 'application/xml', 'HTTP_DEPTH' => "1"]);
        $body = <<<BLA
<?xml version="1.0" encoding="utf-8" ?>
<D:sync-collection xmlns:D="DAV:">
     <D:sync-token>http://sabre.io/ns/sync/1</D:sync-token>
      <D:prop>
        <D:getcontentlength/>
      </D:prop>
</D:sync-collection>
BLA;
        $request->setBody($body);
        $response = $this->request($request);
        $this->assertEquals(207, $response->status, 'Full response body:' . $response->body);
        $dom = DAV\XMLUtil::loadDOMDocument($response->body);
        // Checking the sync-token
        $this->assertEquals('http://sabre.io/ns/sync/2', $dom->getElementsByTagNameNS('urn:DAV', 'sync-token')->item(0)->nodeValue);
        $responses = DAV\Property\ResponseList::unserialize($dom->documentElement, []);
        $responses = $responses->getResponses();
        $this->assertEquals(2, count($responses), 'We expected exactly 2 {DAV:}response');
        $response = $responses[0];
        $this->assertNull($response->getHttpStatus());
        $this->assertEquals('/coll/file2.txt', $response->getHref());
        $this->assertEquals([200 => ['{DAV:}getcontentlength' => 3]], $response->getResponseProperties());
        $response = $responses[1];
        $this->assertEquals('404', $response->getHttpStatus());
        $this->assertEquals('/coll/file3.txt', $response->getHref());
        $this->assertEquals([], $response->getResponseProperties());
    }
Ejemplo n.º 9
0
    /**
     * @expectedException Sabre\DAV\Exception\BadRequest
     */
    function testUnserializeMissingPriv()
    {
        $source = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:">
  <d:ace>
    <d:grant>
      <d:privilege />
    </d:grant>
    <d:principal><d:href>/principals/evert</d:href></d:principal>
  </d:ace>
</d:root>
';
        $dom = DAV\XMLUtil::loadDOMDocument($source);
        Acl::unserialize($dom->firstChild, array());
    }
Ejemplo n.º 10
0
    /**
     * @expectedException Sabre\DAV\Exception\BadRequest
     */
    function testExpandBadTimes()
    {
        $xml = array('<d:prop>', '  <c:calendar-data>', '     <c:expand start="20120101T000000Z" end="19980101T000000Z"/>', '  </c:calendar-data>', '</d:prop>', '<c:filter>', '  <c:comp-filter name="VCALENDAR" />', '</c:filter>');
        $xml = '<?xml version="1.0"?>
<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">
' . implode("\n", $xml) . '
</c:calendar-query>';
        $dom = DAV\XMLUtil::loadDOMDocument($xml);
        $q = new CalendarQueryParser($dom);
        $q->parse();
    }
Ejemplo n.º 11
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;
 }
Ejemplo n.º 12
0
 /**
  * This method is responsible for handling the 'ACL' event.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpAcl(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     $body = $request->getBodyAsString();
     $dom = DAV\XMLUtil::loadDOMDocument($body);
     $newAcl = Property\Acl::unserialize($dom->firstChild, $this->server->propertyMap)->getPrivileges();
     // Normalizing urls
     foreach ($newAcl as $k => $newAce) {
         $newAcl[$k]['principal'] = $this->server->calculateUri($newAce['principal']);
     }
     $node = $this->server->tree->getNodeForPath($path);
     if (!$node instanceof IACL) {
         throw new DAV\Exception\MethodNotAllowed('This node does not support the ACL method');
     }
     $oldAcl = $this->getACL($node);
     $supportedPrivileges = $this->getFlatPrivilegeSet($node);
     /* Checking if protected principals from the existing principal set are
        not overwritten. */
     foreach ($oldAcl as $oldAce) {
         if (!isset($oldAce['protected']) || !$oldAce['protected']) {
             continue;
         }
         $found = false;
         foreach ($newAcl as $newAce) {
             if ($newAce['privilege'] === $oldAce['privilege'] && $newAce['principal'] === $oldAce['principal'] && $newAce['protected']) {
                 $found = true;
             }
         }
         if (!$found) {
             throw new Exception\AceConflict('This resource contained a protected {DAV:}ace, but this privilege did not occur in the ACL request');
         }
     }
     foreach ($newAcl as $newAce) {
         // Do we recognize the privilege
         if (!isset($supportedPrivileges[$newAce['privilege']])) {
             throw new Exception\NotSupportedPrivilege('The privilege you specified (' . $newAce['privilege'] . ') is not recognized by this server');
         }
         if ($supportedPrivileges[$newAce['privilege']]['abstract']) {
             throw new Exception\NoAbstract('The privilege you specified (' . $newAce['privilege'] . ') is an abstract privilege');
         }
         // Looking up the principal
         try {
             $principal = $this->server->tree->getNodeForPath($newAce['principal']);
         } catch (DAV\Exception\NotFound $e) {
             throw new Exception\NotRecognizedPrincipal('The specified principal (' . $newAce['principal'] . ') does not exist');
         }
         if (!$principal instanceof IPrincipal) {
             throw new Exception\NotRecognizedPrincipal('The specified uri (' . $newAce['principal'] . ') is not a principal');
         }
     }
     $node->setACL($newAcl);
     $response->setStatus(200);
     // Breaking the event chain, because we handled this method.
     return false;
 }
Ejemplo n.º 13
0
    /**
     * @expectedException Sabre\DAV\Exception\BadRequest
     */
    function testUnserializeUnknown()
    {
        $xml = '<?xml version="1.0"?>
<d:principal xmlns:d="DAV:">' . '  <d:foo />' . '</d:principal>';
        $dom = DAV\XMLUtil::loadDOMDocument($xml);
        Principal::unserialize($dom->firstChild, array());
    }
Ejemplo n.º 14
0
    /**
     * @expectedException Sabre\DAV\Exception
     */
    function testFreeBusyReportNoACLPlugin()
    {
        $this->server = new DAV\Server();
        $this->plugin = new Plugin();
        $this->server->addPlugin($this->plugin);
        $reportXML = <<<XML
<?xml version="1.0"?>
<c:free-busy-query xmlns:c="urn:ietf:params:xml:ns:caldav">
    <c:time-range start="20111001T000000Z" end="20111101T000000Z" />
</c:free-busy-query>
XML;
        $dom = DAV\XMLUtil::loadDOMDocument($reportXML);
        $this->plugin->report('{urn:ietf:params:xml:ns:caldav}free-busy-query', $dom);
    }
Ejemplo n.º 15
0
 /**
  * This method parses the PROPFIND request and returns its information
  *
  * This will either be a list of properties, or an empty array; in which case
  * an {DAV:}allprop was requested.
  *
  * @param string $body
  * @return array
  */
 public function parsePropFindRequest($body)
 {
     // If the propfind body was empty, it means IE is requesting 'all' properties
     if (!$body) {
         return array();
     }
     $dom = XMLUtil::loadDOMDocument($body);
     $elem = $dom->getElementsByTagNameNS('urn:DAV', 'propfind')->item(0);
     return array_keys(XMLUtil::parseProperties($elem));
 }
Ejemplo n.º 16
0
    /**
     * @expectedException Sabre\DAV\Exception
     */
    function testUnserializeNoStatus()
    {
        $xml = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:" xmlns:cal="' . CalDAV\Plugin::NS_CALDAV . '" xmlns:cs="' . CalDAV\Plugin::NS_CALENDARSERVER . '">
  <cs:user>
    <d:href>mailto:user1@example.org</d:href>
    <!-- <cs:invite-accepted/> -->
    <cs:access>
      <cs:read-write/>
    </cs:access>
  </cs:user>
</d:root>';
        $doc2 = DAV\XMLUtil::loadDOMDocument($xml);
        $outputProperty = Invite::unserialize($doc2->firstChild);
    }
Ejemplo n.º 17
0
 /**
  * This function handles the MKCALENDAR HTTP method, which creates
  * a new calendar.
  *
  * @param string $uri
  * @return void
  */
 public function httpMkCalendar($uri)
 {
     // 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 = $this->server->httpRequest->getBody(true);
     $properties = array();
     if ($body) {
         $dom = DAV\XMLUtil::loadDOMDocument($body);
         foreach ($dom->firstChild->childNodes as $child) {
             if (DAV\XMLUtil::toClarkNotation($child) !== '{DAV:}set') {
                 continue;
             }
             foreach (DAV\XMLUtil::parseProperties($child, $this->server->propertyMap) as $k => $prop) {
                 $properties[$k] = $prop;
             }
         }
     }
     $resourceType = array('{DAV:}collection', '{urn:ietf:params:xml:ns:caldav}calendar');
     $this->server->createCollection($uri, $resourceType, $properties);
     $this->server->httpResponse->sendStatus(201);
     $this->server->httpResponse->setHeader('Content-Length', 0);
 }
Ejemplo n.º 18
0
 /**
  * This method parses the PROPFIND request and returns its information
  *
  * This will either be a list of properties, or an empty array; in which case
  * an {DAV:}allprop was requested.
  *
  * @param string $body
  * @return array
  */
 function parsePropFindRequest($body)
 {
     // If the propfind body was empty, it means IE is requesting 'all' properties
     if (!$body) {
         return [];
     }
     $dom = XMLUtil::loadDOMDocument($body);
     $elem = $dom->getElementsByTagNameNS('urn:DAV', 'propfind')->item(0);
     if (is_null($elem)) {
         throw new Exception\UnsupportedMediaType('We could not find a {DAV:}propfind element in the xml request body');
     }
     return array_keys(XMLUtil::parseProperties($elem));
 }
Ejemplo n.º 19
0
    function testCalendarQueryDepth0()
    {
        $xml = <<<XML
<?xml version="1.0"?>
<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">
    <d:prop>
        <c:calendar-data content-type="application/calendar+json" />
    </d:prop>
    <c:filter>
        <c:comp-filter name="VCALENDAR" />
    </c:filter>
</c:calendar-query>
XML;
        $headers = ['Depth' => '0'];
        $request = new Request('REPORT', '/calendars/user1/foo/bar.ics', $headers, $xml);
        $response = $this->request($request);
        $this->assertEquals(207, $response->getStatus(), "Invalid response code. Full body: " . $response->getBodyAsString());
        $body = $response->getBodyAsString();
        // Getting from the xml body to the actual returned data is
        // unfortunately very convoluted.
        $responses = \Sabre\DAV\Property\ResponseList::unserialize(\Sabre\DAV\XMLUtil::loadDOMDocument($body)->firstChild, $this->server->propertyMap);
        $responses = $responses->getResponses();
        $this->assertEquals(1, count($responses));
        $response = $responses[0]->getResponseProperties()[200]["{urn:ietf:params:xml:ns:caldav}calendar-data"];
        $response = json_decode($response, true);
        if (json_last_error()) {
            $this->fail('Json decoding error: ' . json_last_error_msg());
        }
        $this->assertEquals(['vcalendar', [], [['vevent', [], []]]], $response);
    }
Ejemplo n.º 20
0
 /**
  * Parses a WebDAV multistatus response body
  *
  * This method returns an array with the following structure
  *
  * [
  *   'url/to/resource' => [
  *     '200' => [
  *        '{DAV:}property1' => 'value1',
  *        '{DAV:}property2' => 'value2',
  *     ],
  *     '404' => [
  *        '{DAV:}property1' => null,
  *        '{DAV:}property2' => null,
  *     ],
  *   ],
  *   'url/to/resource2' => [
  *      .. etc ..
  *   ]
  * ]
  *
  *
  * @param string $body xml body
  * @return array
  */
 function parseMultiStatus($body)
 {
     try {
         $dom = XMLUtil::loadDOMDocument($body);
     } catch (Exception\BadRequest $e) {
         throw new \InvalidArgumentException('The body passed to parseMultiStatus could not be parsed. Is it really xml?');
     }
     $responses = Property\ResponseList::unserialize($dom->documentElement, $this->propertyMap);
     $result = [];
     foreach ($responses->getResponses() as $response) {
         $result[$response->getHref()] = $response->getResponseProperties();
     }
     return $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;
             }
     }
 }
Ejemplo n.º 22
0
 /**
  * This function handles the MKCALENDAR HTTP method, which creates
  * a new calendar.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 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();
     $properties = [];
     if ($body) {
         $dom = DAV\XMLUtil::loadDOMDocument($body);
         foreach ($dom->firstChild->childNodes as $child) {
             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
     // subscriptions. Before that it used MKCOL which was the correct way
     // to do this.
     //
     // If the body had a {DAV:}resourcetype, it means we stumbled upon this
     // request, and we simply use it instead of the pre-defined list.
     if (isset($properties['{DAV:}resourcetype'])) {
         $resourceType = $properties['{DAV:}resourcetype']->getValue();
     } else {
         $resourceType = ['{DAV:}collection', '{urn:ietf:params:xml:ns:caldav}calendar'];
     }
     $this->server->createCollection($path, $resourceType, $properties);
     $this->server->httpResponse->setStatus(201);
     $this->server->httpResponse->setHeader('Content-Length', 0);
     // This breaks the method chain.
     return false;
 }
Ejemplo n.º 23
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;
     }
 }