コード例 #1
0
 /**
  * Intercepts GET requests on addressbook urls ending with ?photo.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool|void
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     $queryParams = $request->getQueryParameters();
     // TODO: in addition to photo we should also add logo some point in time
     if (!array_key_exists('photo', $queryParams)) {
         return true;
     }
     $path = $request->getPath();
     $node = $this->server->tree->getNodeForPath($path);
     if (!$node instanceof Card) {
         return true;
     }
     $this->server->transactionType = 'carddav-image-export';
     // Checking ACL, if available.
     if ($aclPlugin = $this->server->getPlugin('acl')) {
         /** @var \Sabre\DAVACL\Plugin $aclPlugin */
         $aclPlugin->checkPrivileges($path, '{DAV:}read');
     }
     if ($result = $this->getPhoto($node)) {
         $response->setHeader('Content-Type', $result['Content-Type']);
         $response->setStatus(200);
         $response->setBody($result['body']);
         // Returning false to break the event chain
         return false;
     }
     return true;
 }
コード例 #2
0
 /**
  * Intercepts GET requests on addressbook urls ending with ?export.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     $queryParams = $request->getQueryParameters();
     if (!array_key_exists('export', $queryParams)) {
         return;
     }
     $path = $request->getPath();
     $node = $this->server->tree->getNodeForPath($path);
     if (!$node instanceof IAddressBook) {
         return;
     }
     $this->server->transactionType = 'get-addressbook-export';
     // Checking ACL, if available.
     if ($aclPlugin = $this->server->getPlugin('acl')) {
         $aclPlugin->checkPrivileges($path, '{DAV:}read');
     }
     $nodes = $this->server->getPropertiesForPath($path, ['{' . Plugin::NS_CARDDAV . '}address-data'], 1);
     $format = 'text/directory';
     $output = null;
     $filenameExtension = null;
     switch ($format) {
         case 'text/directory':
             $output = $this->generateVCF($nodes);
             $filenameExtension = '.vcf';
             break;
     }
     $filename = preg_replace('/[^a-zA-Z0-9-_ ]/um', '', $node->getName());
     $filename .= '-' . date('Y-m-d') . $filenameExtension;
     $response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
     $response->setHeader('Content-Type', $format);
     $response->setStatus(200);
     $response->setBody($output);
     // Returning false to break the event chain
     return false;
 }
コード例 #3
0
 /**
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return false
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     $string = 'This is the WebDAV interface. It can only be accessed by ' . 'WebDAV clients such as the WebDAV Nav sync client.';
     $stream = fopen('php://memory', 'r+');
     fwrite($stream, $string);
     rewind($stream);
     $response->setBody($stream);
     return false;
 }
コード例 #4
0
ファイル: Plugin.php プロジェクト: Kevin-ZK/vaneDisk
 /**
  * Generates the davmount response
  *
  * @param string $uri absolute uri
  * @return void
  */
 function davMount(ResponseInterface $response, $uri)
 {
     $response->setStatus(200);
     $response->setHeader('Content-Type', 'application/davmount+xml');
     ob_start();
     echo '<?xml version="1.0"?>', "\n";
     echo "<dm:mount xmlns:dm=\"http://purl.org/NET/webdav/mount\">\n";
     echo "  <dm:url>", htmlspecialchars($uri, ENT_NOQUOTES, 'UTF-8'), "</dm:url>\n";
     echo "</dm:mount>";
     $response->setBody(ob_get_clean());
 }
コード例 #5
0
 /**
  * Intercepts GET requests on addressbook urls ending with ?export.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     $queryParams = $request->getQueryParameters();
     if (!array_key_exists('export', $queryParams)) {
         return;
     }
     $path = $request->getPath();
     $node = $this->server->tree->getNodeForPath($path);
     if (!$node instanceof IAddressBook) {
         return;
     }
     $this->server->transactionType = 'get-addressbook-export';
     // Checking ACL, if available.
     if ($aclPlugin = $this->server->getPlugin('acl')) {
         $aclPlugin->checkPrivileges($path, '{DAV:}read');
     }
     $response->setHeader('Content-Type', 'text/directory');
     $response->setStatus(200);
     $nodes = $this->server->getPropertiesForPath($path, ['{' . Plugin::NS_CARDDAV . '}address-data'], 1);
     $response->setBody($this->generateVCF($nodes));
     // Returning false to break the event chain
     return false;
 }
コード例 #6
0
ファイル: Plugin.php プロジェクト: BlaBlaNet/hubzilla
 /**
  * Locks an uri
  *
  * The WebDAV lock request can be operated to either create a new lock on a file, or to refresh an existing lock
  * If a new lock is created, a full XML body should be supplied, containing information about the lock such as the type
  * of lock (shared or exclusive) and the owner of the lock
  *
  * If a lock is to be refreshed, no body should be supplied and there should be a valid If header containing the lock
  *
  * Additionally, a lock can be requested for a non-existent file. In these case we're obligated to create an empty file as per RFC4918:S7.3
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpLock(RequestInterface $request, ResponseInterface $response)
 {
     $uri = $request->getPath();
     $existingLocks = $this->getLocks($uri);
     if ($body = $request->getBodyAsString()) {
         // This is a new lock request
         $existingLock = null;
         // Checking if there's already non-shared locks on the uri.
         foreach ($existingLocks as $existingLock) {
             if ($existingLock->scope === LockInfo::EXCLUSIVE) {
                 throw new DAV\Exception\ConflictingLock($existingLock);
             }
         }
         $lockInfo = $this->parseLockRequest($body);
         $lockInfo->depth = $this->server->getHTTPDepth();
         $lockInfo->uri = $uri;
         if ($existingLock && $lockInfo->scope != LockInfo::SHARED) {
             throw new DAV\Exception\ConflictingLock($existingLock);
         }
     } else {
         // Gonna check if this was a lock refresh.
         $existingLocks = $this->getLocks($uri);
         $conditions = $this->server->getIfConditions($request);
         $found = null;
         foreach ($existingLocks as $existingLock) {
             foreach ($conditions as $condition) {
                 foreach ($condition['tokens'] as $token) {
                     if ($token['token'] === 'opaquelocktoken:' . $existingLock->token) {
                         $found = $existingLock;
                         break 3;
                     }
                 }
             }
         }
         // If none were found, this request is in error.
         if (is_null($found)) {
             if ($existingLocks) {
                 throw new DAV\Exception\Locked(reset($existingLocks));
             } else {
                 throw new DAV\Exception\BadRequest('An xml body is required for lock requests');
             }
         }
         // This must have been a lock refresh
         $lockInfo = $found;
         // The resource could have been locked through another uri.
         if ($uri != $lockInfo->uri) {
             $uri = $lockInfo->uri;
         }
     }
     if ($timeout = $this->getTimeoutHeader()) {
         $lockInfo->timeout = $timeout;
     }
     $newFile = false;
     // If we got this far.. we should go check if this node actually exists. If this is not the case, we need to create it first
     try {
         $this->server->tree->getNodeForPath($uri);
         // We need to call the beforeWriteContent event for RFC3744
         // Edit: looks like this is not used, and causing problems now.
         //
         // See Issue 222
         // $this->server->emit('beforeWriteContent',array($uri));
     } catch (DAV\Exception\NotFound $e) {
         // It didn't, lets create it
         $this->server->createFile($uri, fopen('php://memory', 'r'));
         $newFile = true;
     }
     $this->lockNode($uri, $lockInfo);
     $response->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $response->setHeader('Lock-Token', '<opaquelocktoken:' . $lockInfo->token . '>');
     $response->setStatus($newFile ? 201 : 200);
     $response->setBody($this->generateLockResponse($lockInfo));
     // Returning false will interupt the event chain and mark this method
     // as 'handled'.
     return false;
 }
コード例 #7
0
ファイル: Plugin.php プロジェクト: LobbyOS/server
 /**
  * This method is responsible for parsing a free-busy query request and
  * returning it's result.
  *
  * @param IOutbox $outbox
  * @param VObject\Component $vObject
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return string
  */
 protected function handleFreeBusyRequest(IOutbox $outbox, VObject\Component $vObject, RequestInterface $request, ResponseInterface $response)
 {
     $vFreeBusy = $vObject->VFREEBUSY;
     $organizer = $vFreeBusy->organizer;
     $organizer = (string) $organizer;
     // Validating if the organizer matches the owner of the inbox.
     $owner = $outbox->getOwner();
     $caldavNS = '{' . self::NS_CALDAV . '}';
     $uas = $caldavNS . 'calendar-user-address-set';
     $props = $this->server->getProperties($owner, [$uas]);
     if (empty($props[$uas]) || !in_array($organizer, $props[$uas]->getHrefs())) {
         throw new Forbidden('The organizer in the request did not match any of the addresses for the owner of this inbox');
     }
     if (!isset($vFreeBusy->ATTENDEE)) {
         throw new BadRequest('You must at least specify 1 attendee');
     }
     $attendees = [];
     foreach ($vFreeBusy->ATTENDEE as $attendee) {
         $attendees[] = (string) $attendee;
     }
     if (!isset($vFreeBusy->DTSTART) || !isset($vFreeBusy->DTEND)) {
         throw new BadRequest('DTSTART and DTEND must both be specified');
     }
     $startRange = $vFreeBusy->DTSTART->getDateTime();
     $endRange = $vFreeBusy->DTEND->getDateTime();
     $results = [];
     foreach ($attendees as $attendee) {
         $results[] = $this->getFreeBusyForEmail($attendee, $startRange, $endRange, $vObject);
     }
     $dom = new \DOMDocument('1.0', 'utf-8');
     $dom->formatOutput = true;
     $scheduleResponse = $dom->createElement('cal:schedule-response');
     foreach ($this->server->xmlNamespaces as $namespace => $prefix) {
         $scheduleResponse->setAttribute('xmlns:' . $prefix, $namespace);
     }
     $dom->appendChild($scheduleResponse);
     foreach ($results as $result) {
         $xresponse = $dom->createElement('cal:response');
         $recipient = $dom->createElement('cal:recipient');
         $recipientHref = $dom->createElement('d:href');
         $recipientHref->appendChild($dom->createTextNode($result['href']));
         $recipient->appendChild($recipientHref);
         $xresponse->appendChild($recipient);
         $reqStatus = $dom->createElement('cal:request-status');
         $reqStatus->appendChild($dom->createTextNode($result['request-status']));
         $xresponse->appendChild($reqStatus);
         if (isset($result['calendar-data'])) {
             $calendardata = $dom->createElement('cal:calendar-data');
             $calendardata->appendChild($dom->createTextNode(str_replace("\r\n", "\n", $result['calendar-data']->serialize())));
             $xresponse->appendChild($calendardata);
         }
         $scheduleResponse->appendChild($xresponse);
     }
     $response->setStatus(200);
     $response->setHeader('Content-Type', 'application/xml');
     $response->setBody($dom->saveXML());
 }
コード例 #8
0
ファイル: Plugin.php プロジェクト: MetallianFR68/myroundcube
 /**
  * This event is triggered before the usual GET request handler.
  *
  * We use this to intercept GET calls to notification nodes, and return the
  * proper response.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return void
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     try {
         $node = $this->server->tree->getNodeForPath($path);
     } catch (DAV\Exception\NotFound $e) {
         return;
     }
     if (!$node instanceof INode) {
         return;
     }
     $dom = new \DOMDocument('1.0', 'UTF-8');
     $dom->formatOutput = true;
     $root = $dom->createElement('cs:notification');
     foreach ($this->server->xmlNamespaces as $namespace => $prefix) {
         $root->setAttribute('xmlns:' . $prefix, $namespace);
     }
     $dom->appendChild($root);
     $node->getNotificationType()->serializeBody($this->server, $root);
     $response->setHeader('Content-Type', 'application/xml');
     $response->setHeader('ETag', $node->getETag());
     $response->setStatus(200);
     $response->setBody($dom->saveXML());
     // Return false to break the event chain.
     return false;
 }
コード例 #9
0
 /**
  * WebDAV MKCOL
  *
  * The MKCOL method is used to create a new collection (directory) on the server
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpMkcol(RequestInterface $request, ResponseInterface $response)
 {
     $requestBody = $request->getBodyAsString();
     $path = $request->getPath();
     if ($requestBody) {
         $contentType = $request->getHeader('Content-Type');
         if (strpos($contentType, 'application/xml') !== 0 && strpos($contentType, 'text/xml') !== 0) {
             // We must throw 415 for unsupported mkcol bodies
             throw new Exception\UnsupportedMediaType('The request body for the MKCOL request must have an xml Content-Type');
         }
         $dom = XMLUtil::loadDOMDocument($requestBody);
         if (XMLUtil::toClarkNotation($dom->firstChild) !== '{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) {
             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');
         }
         $resourceType = $properties['{DAV:}resourcetype']->getValue();
         unset($properties['{DAV:}resourcetype']);
     } else {
         $properties = [];
         $resourceType = ['{DAV:}collection'];
     }
     $result = $this->server->createCollection($path, $resourceType, $properties);
     if (is_array($result)) {
         $response->setStatus(207);
         $response->setHeader('Content-Type', 'application/xml; charset=utf-8');
         $response->setBody($this->server->generateMultiStatus([$result]));
     } else {
         $response->setHeader('Content-Length', '0');
         $response->setStatus(201);
     }
     // Sending back false will interupt the event chain and tell the server
     // we've handled this method.
     return false;
 }
コード例 #10
0
 /**
  * Fakes a successful LOCK
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 public function fakeLockProvider(RequestInterface $request, ResponseInterface $response)
 {
     $lockInfo = new LockInfo();
     $lockInfo->token = md5($request->getPath());
     $lockInfo->uri = $request->getPath();
     $lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
     $lockInfo->timeout = 1800;
     $body = $this->server->xml->write('{DAV:}prop', ['{DAV:}lockdiscovery' => new LockDiscovery([$lockInfo])]);
     $response->setBody($body);
     return false;
 }
コード例 #11
0
 /**
  * This method handles the PROPFIND method.
  *
  * It's a very lazy method, it won't bother checking the request body
  * for which properties were requested, and just sends back a default
  * set of properties.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $hR
  * @param string $tempLocation
  * @return bool
  */
 function httpPropfind(RequestInterface $request, ResponseInterface $hR, $tempLocation)
 {
     if (!file_exists($tempLocation)) {
         return;
     }
     $hR->setHeader('X-Sabre-Temp', 'true');
     $hR->setStatus(207);
     $hR->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $properties = ['href' => $request->getPath(), 200 => ['{DAV:}getlastmodified' => new Xml\Property\GetLastModified(filemtime($tempLocation)), '{DAV:}getcontentlength' => filesize($tempLocation), '{DAV:}resourcetype' => new Xml\Property\ResourceType(null), '{' . Server::NS_SABREDAV . '}tempFile' => true]];
     $data = $this->server->generateMultiStatus([$properties]);
     $hR->setBody($data);
     return false;
 }
コード例 #12
0
ファイル: Plugin.php プロジェクト: LobbyOS/server
 /**
  * This method intercepts GET requests to collections and returns the html
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     // We're not using straight-up $_GET, because we want everything to be
     // unit testable.
     $getVars = $request->getQueryParameters();
     $sabreAction = isset($getVars['sabreAction']) ? $getVars['sabreAction'] : null;
     // Asset handling, such as images
     if ($sabreAction === 'asset' && isset($getVars['assetName'])) {
         $this->serveAsset($getVars['assetName']);
         return false;
     }
     try {
         $this->server->tree->getNodeForPath($request->getPath());
     } catch (DAV\Exception\NotFound $e) {
         // We're simply stopping when the file isn't found to not interfere
         // with other plugins.
         return;
     }
     $response->setStatus(200);
     $response->setHeader('Content-Type', 'text/html; charset=utf-8');
     $response->setBody($this->generateDirectoryIndex($request->getPath()));
     return false;
 }
コード例 #13
0
ファイル: Plugin.php プロジェクト: lkraav/sabre-katana
 /**
  * Compute an HTTP POST method.
  *
  * @param  Request   $request     HTTP request.
  * @param  Response  $response    HTTP response.
  * @return bool
  * @throws Exception\Dav\Exception
  */
 function httpPost(Request $request, Response $response)
 {
     if (System\Collection::NAME . '/' . Node::NAME !== $request->getPath()) {
         return;
     }
     $payload = @json_decode($request->getBodyAsString());
     if (!$payload || !isset($payload->transport) || !isset($payload->username) || !isset($payload->password)) {
         throw new Exception\Dav\Exception('Payload is corrupted.');
     }
     $this->configuration->mail = new StdClass();
     $this->configuration->mail->transport = $payload->transport;
     $this->configuration->mail->username = $payload->username;
     $this->configuration->mail->password = $payload->password;
     $this->configuration->save();
     $response->setHeader('Content-Type', 'application/json');
     $response->setBody(json_encode(true));
     return false;
 }
コード例 #14
0
ファイル: ICSExportPlugin.php プロジェクト: LobbyOS/server
 /**
  * This method is responsible for generating the actual, full response.
  *
  * @param string $path
  * @param DateTime|null $start
  * @param DateTime|null $end
  * @param bool $expand
  * @param string $format
  * @param array $properties
  * @param ResponseInterface $response
  */
 protected function generateResponse($path, $start, $end, $expand, $format, $properties, ResponseInterface $response)
 {
     $calDataProp = '{' . Plugin::NS_CALDAV . '}calendar-data';
     $blobs = [];
     if ($start || $end) {
         // If there was a start or end filter, we need to enlist
         // calendarQuery for speed.
         $calendarNode = $this->server->tree->getNodeForPath($path);
         $queryResult = $calendarNode->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]);
         // queryResult is just a list of base urls. We need to prefix the
         // calendar path.
         $queryResult = array_map(function ($item) use($path) {
             return $path . '/' . $item;
         }, $queryResult);
         $nodes = $this->server->getPropertiesForMultiplePaths($queryResult, [$calDataProp]);
         unset($queryResult);
     } else {
         $nodes = $this->server->getPropertiesForPath($path, [$calDataProp], 1);
     }
     // Flattening the arrays
     foreach ($nodes as $node) {
         if (isset($node[200][$calDataProp])) {
             $blobs[] = $node[200][$calDataProp];
         }
     }
     unset($nodes);
     $mergedCalendar = $this->mergeObjects($properties, $blobs);
     if ($expand) {
         $mergedCalendar->expand($start, $end);
     }
     $response->setHeader('Content-Type', $format);
     switch ($format) {
         case 'text/calendar':
             $mergedCalendar = $mergedCalendar->serialize();
             break;
         case 'application/calendar+json':
             $mergedCalendar = json_encode($mergedCalendar->jsonSerialize());
             break;
     }
     $response->setStatus(200);
     $response->setBody($mergedCalendar);
 }
コード例 #15
0
ファイル: Plugin.php プロジェクト: nurtext/sabre-katana
 /**
  * @return bool
  */
 function httpGet(Request $request, Response $response)
 {
     if (System\Collection::NAME . '/' . Node::NAME !== $request->getPath()) {
         return;
     }
     $payload = ['current_version' => SABRE_KATANA_VERSION];
     $extra = [];
     if (true === $request->hasHeader('Referer')) {
         $extra['referer'] = $request->getHeader('Referer');
     }
     $updatesDotJson = Updater::getUpdateUrl(Updater::DEFAULT_UPDATE_SERVER, $extra);
     $versions = @file_get_contents($updatesDotJson);
     if (!empty($versions)) {
         $versions = json_decode($versions, true);
         $versionsToFetch = Updater::filterVersions($versions, SABRE_KATANA_VERSION, Updater::FORMAT_PHAR);
         $payload['next_versions'] = array_keys($versionsToFetch);
     }
     $response->setHeader('Content-Type', 'application/json');
     $response->setBody(json_encode($payload));
     return false;
 }
コード例 #16
0
ファイル: Plugin.php プロジェクト: nikosv/openeclass
    /**
     * This event is triggered before the usual GET request handler.
     *
     * We use this to intercept GET calls to notification nodes, and return the
     * proper response.
     *
     * @param RequestInterface $request
     * @param ResponseInterface $response
     * @return void
     */
    function httpGet(RequestInterface $request, ResponseInterface $response) {

        $path = $request->getPath();

        try {
            $node = $this->server->tree->getNodeForPath($path);
        } catch (DAV\Exception\NotFound $e) {
            return;
        }

        if (!$node instanceof INode)
            return;

        $writer = $this->server->xml->getWriter();
        $writer->contextUri = $this->server->getBaseUri();
        $writer->openMemory();
        $writer->startDocument('1.0', 'UTF-8');
        $writer->startElement('{http://calendarserver.org/ns/}notification');
        $node->getNotificationType()->xmlSerializeFull($writer);
        $writer->endElement();

        $response->setHeader('Content-Type', 'application/xml');
        $response->setHeader('ETag', $node->getETag());
        $response->setStatus(200);
        $response->setBody($writer->outputMemory());

        // Return false to break the event chain.
        return false;

    }
コード例 #17
0
ファイル: ICSExportPlugin.php プロジェクト: pageer/sabre-dav
 /**
  * This method is responsible for generating the actual, full response.
  *
  * @param string $path
  * @param DateTime|null $start
  * @param DateTime|null $end
  * @param bool $expand
  * @param string $componentType
  * @param string $format
  * @param array $properties
  * @param ResponseInterface $response
  */
 protected function generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, ResponseInterface $response)
 {
     $calDataProp = '{' . Plugin::NS_CALDAV . '}calendar-data';
     $blobs = [];
     if ($start || $end || $componentType) {
         // If there was a start or end filter, we need to enlist
         // calendarQuery for speed.
         $calendarNode = $this->server->tree->getNodeForPath($path);
         $queryResult = $calendarNode->calendarQuery(['name' => 'VCALENDAR', 'comp-filters' => [['name' => $componentType, 'comp-filters' => [], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => ['start' => $start, 'end' => $end]]], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => null]);
         // queryResult is just a list of base urls. We need to prefix the
         // calendar path.
         $queryResult = array_map(function ($item) use($path) {
             return $path . '/' . $item;
         }, $queryResult);
         $nodes = $this->server->getPropertiesForMultiplePaths($queryResult, [$calDataProp]);
         unset($queryResult);
     } else {
         $nodes = $this->server->getPropertiesForPath($path, [$calDataProp], 1);
     }
     // Flattening the arrays
     foreach ($nodes as $node) {
         if (isset($node[200][$calDataProp])) {
             $blobs[$node['href']] = $node[200][$calDataProp];
         }
     }
     unset($nodes);
     $mergedCalendar = $this->mergeObjects($properties, $blobs);
     if ($expand) {
         $calendarTimeZone = null;
         // We're expanding, and for that we need to figure out the
         // calendar's timezone.
         $tzProp = '{' . Plugin::NS_CALDAV . '}calendar-timezone';
         $tzResult = $this->server->getProperties($path, [$tzProp]);
         if (isset($tzResult[$tzProp])) {
             // This property contains a VCALENDAR with a single
             // VTIMEZONE.
             $vtimezoneObj = VObject\Reader::read($tzResult[$tzProp]);
             $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone();
             // Destroy circular references to PHP will GC the object.
             $vtimezoneObj->destroy();
             unset($vtimezoneObj);
         } else {
             // Defaulting to UTC.
             $calendarTimeZone = new DateTimeZone('UTC');
         }
         $mergedCalendar->expand($start, $end, $calendarTimeZone);
     }
     $response->setHeader('Content-Type', $format);
     switch ($format) {
         case 'text/calendar':
             $mergedCalendar = $mergedCalendar->serialize();
             break;
         case 'application/calendar+json':
             $mergedCalendar = json_encode($mergedCalendar->jsonSerialize());
             break;
     }
     $response->setStatus(200);
     $response->setBody($mergedCalendar);
 }
コード例 #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 (DAV\Exception\NotFound $e) {
         return;
     }
     $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 = 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;
             }
             $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;
             // 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 CalendarHome) {
                 return;
             }
             $this->server->transactionType = 'post-invite-reply';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $message = $this->parseInviteReplyRequest($dom);
             $url = $node->shareReply($message['href'], $message['status'], $message['calendarUri'], $message['inReplyTo'], $message['summary']);
             $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');
             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);
                 $response->setHeader('Content-Type', 'application/xml');
                 $response->setBody($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;
             }
             $this->server->transactionType = 'post-publish-calendar';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $node->setPublishStatus(true);
             // iCloud sends back the 202, so we will too.
             $response->setStatus(202);
             // 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;
         case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableCalendar) {
                 return;
             }
             $this->server->transactionType = 'post-unpublish-calendar';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $node->setPublishStatus(false);
             $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;
     }
 }
コード例 #19
0
ファイル: Plugin.php プロジェクト: sebbie42/casebox
 /**
  * This event is triggered after GET requests.
  *
  * This is used to transform data into jCal, if this was requested.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return void
  */
 function httpAfterGet(RequestInterface $request, ResponseInterface $response)
 {
     if (strpos($response->getHeader('Content-Type'), 'text/calendar') === false) {
         return;
     }
     $result = HTTP\Util::negotiate($request->getHeader('Accept'), ['text/calendar', 'application/calendar+json']);
     if ($result !== 'application/calendar+json') {
         // Do nothing
         return;
     }
     // Transforming.
     $vobj = VObject\Reader::read($response->getBody());
     $jsonBody = json_encode($vobj->jsonSerialize());
     $response->setBody($jsonBody);
     $response->setHeader('Content-Type', 'application/calendar+json');
     $response->setHeader('Content-Length', strlen($jsonBody));
 }
コード例 #20
0
ファイル: Plugin.php プロジェクト: pageer/sabre-dav
 /**
  * This method intercepts GET requests to collections and returns the html
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpGet(RequestInterface $request, ResponseInterface $response)
 {
     // We're not using straight-up $_GET, because we want everything to be
     // unit testable.
     $getVars = $request->getQueryParameters();
     // CSP headers
     $this->server->httpResponse->setHeader('Content-Security-Policy', "img-src 'self'; style-src 'self';");
     $sabreAction = isset($getVars['sabreAction']) ? $getVars['sabreAction'] : null;
     switch ($sabreAction) {
         case 'asset':
             // Asset handling, such as images
             $this->serveAsset(isset($getVars['assetName']) ? $getVars['assetName'] : null);
             return false;
         default:
         case 'info':
             try {
                 $this->server->tree->getNodeForPath($request->getPath());
             } catch (DAV\Exception\NotFound $e) {
                 // We're simply stopping when the file isn't found to not interfere
                 // with other plugins.
                 return;
             }
             $response->setStatus(200);
             $response->setHeader('Content-Type', 'text/html; charset=utf-8');
             $response->setBody($this->generateDirectoryIndex($request->getPath()));
             return false;
         case 'plugins':
             $response->setStatus(200);
             $response->setHeader('Content-Type', 'text/html; charset=utf-8');
             $response->setBody($this->generatePluginListing());
             return false;
     }
 }
コード例 #21
0
 /**
  * WebDAV MKCOL
  *
  * The MKCOL method is used to create a new collection (directory) on the server
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpMkcol(RequestInterface $request, ResponseInterface $response)
 {
     $requestBody = $request->getBodyAsString();
     $path = $request->getPath();
     if ($requestBody) {
         $contentType = $request->getHeader('Content-Type');
         if (strpos($contentType, 'application/xml') !== 0 && strpos($contentType, 'text/xml') !== 0) {
             // We must throw 415 for unsupported mkcol bodies
             throw new Exception\UnsupportedMediaType('The request body for the MKCOL request must have an xml Content-Type');
         }
         try {
             $mkcol = $this->server->xml->expect('{DAV:}mkcol', $requestBody);
         } catch (\Sabre\Xml\ParseException $e) {
             throw new Exception\BadRequest($e->getMessage(), null, $e);
         }
         $properties = $mkcol->getProperties();
         if (!isset($properties['{DAV:}resourcetype'])) {
             throw new Exception\BadRequest('The mkcol request must include a {DAV:}resourcetype property');
         }
         $resourceType = $properties['{DAV:}resourcetype']->getValue();
         unset($properties['{DAV:}resourcetype']);
     } else {
         $properties = [];
         $resourceType = ['{DAV:}collection'];
     }
     $mkcol = new MkCol($resourceType, $properties);
     $result = $this->server->createCollection($path, $mkcol);
     if (is_array($result)) {
         $response->setStatus(207);
         $response->setHeader('Content-Type', 'application/xml; charset=utf-8');
         $response->setBody($this->server->generateMultiStatus([$result]));
     } else {
         $response->setHeader('Content-Length', '0');
         $response->setStatus(201);
     }
     // Sending back false will interupt the event chain and tell the server
     // we've handled this method.
     return false;
 }
コード例 #22
0
ファイル: SharingPlugin.php プロジェクト: pageer/sabre-dav
 /**
  * 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 (DAV\Exception\NotFound $e) {
         return;
     }
     $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);
     $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
     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;
             }
             $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');
             }
             $node->updateShares($message->set, $message->remove);
             $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;
             // 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 CalendarHome) {
                 return;
             }
             $this->server->transactionType = 'post-invite-reply';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $url = $node->shareReply($message->href, $message->status, $message->calendarUri, $message->inReplyTo, $message->summary);
             $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');
             if ($url) {
                 $writer = $this->server->xml->getWriter($this->server->getBaseUri());
                 $writer->openMemory();
                 $writer->startDocument();
                 $writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}shared-as');
                 $writer->write(new Href($url));
                 $writer->endElement();
                 $response->setHeader('Content-Type', 'application/xml');
                 $response->setBody($writer->outputMemory());
             }
             // Breaking the event chain
             return false;
         case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableCalendar) {
                 return;
             }
             $this->server->transactionType = 'post-publish-calendar';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $node->setPublishStatus(true);
             // iCloud sends back the 202, so we will too.
             $response->setStatus(202);
             // 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;
         case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof IShareableCalendar) {
                 return;
             }
             $this->server->transactionType = 'post-unpublish-calendar';
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($path, '{DAV:}write');
             }
             $node->setPublishStatus(false);
             $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;
     }
 }
コード例 #23
0
ファイル: Plugin.php プロジェクト: samj1912/repo
 /**
  * This event is triggered after GET requests.
  *
  * This is used to transform data into jCal, if this was requested.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return void
  */
 function httpAfterGet(RequestInterface $request, ResponseInterface $response)
 {
     if (strpos($response->getHeader('Content-Type'), 'text/vcard') === false) {
         return;
     }
     $target = $this->negotiateVCard($request->getHeader('Accept'), $mimeType);
     $newBody = $this->convertVCard($response->getBody(), $target);
     $response->setBody($newBody);
     $response->setHeader('Content-Type', $mimeType . '; charset=utf-8');
     $response->setHeader('Content-Length', strlen($newBody));
 }
コード例 #24
0
ファイル: fakelockerplugin.php プロジェクト: quality123/core
 /**
  * Fakes a successful LOCK
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 public function fakeLockProvider(RequestInterface $request, ResponseInterface $response)
 {
     $dom = new \DOMDocument('1.0', 'utf-8');
     $prop = $dom->createElementNS('DAV:', 'd:prop');
     $dom->appendChild($prop);
     $lockDiscovery = $dom->createElementNS('DAV:', 'd:lockdiscovery');
     $prop->appendChild($lockDiscovery);
     $lockInfo = new LockInfo();
     $lockInfo->token = md5($request->getPath());
     $lockInfo->uri = $request->getPath();
     $lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
     $lockInfo->timeout = 1800;
     $lockObj = new LockDiscovery([$lockInfo]);
     $lockObj->serialize($this->server, $lockDiscovery);
     $response->setBody($dom->saveXML());
     return false;
 }