/** * Implementing Principal Match * * @param DOMDocument $dom */ public function principalMatch(DOMDocument $dom) { $xml = array(array('href' => 'principals/users/' . Tinebase_Core::getUser()->contact_id)); $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->sendBody($this->server->generateMultiStatus($xml)); }
/** * aclPrincipalPropSet REPORT * * This method is responsible for handling the {DAV:}acl-principal-prop-set * REPORT, as defined in: * * https://tools.ietf.org/html/rfc3744#section-9.2 * * This REPORT allows a user to quickly fetch information about all * principals specified in the access control list. Most commonly this * is used to for example generate a UI with ACL rules, allowing you * to show names for principals for every entry. * * @param string $path * @param Xml\Request\AclPrincipalPropSetReport $report * @return void */ protected function aclPrincipalPropSetReport($path, Xml\Request\AclPrincipalPropSetReport $report) { if ($this->server->getHTTPDepth(0) !== 0) { throw new BadRequest('The {DAV:}acl-principal-prop-set REPORT only supports Depth 0'); } // Fetching ACL rules for the given path. We're using the property // API and not the local getACL, because it will ensure that all // business rules and restrictions are applied. $acl = $this->server->getProperties($path, '{DAV:}acl'); if (!$acl || !isset($acl['{DAV:}acl'])) { throw new Forbidden('Could not fetch ACL rules for this path'); } $principals = []; foreach ($acl['{DAV:}acl']->getPrivileges() as $ace) { if ($ace['principal'][0] === '{') { // It's not a principal, it's one of the special rules such as {DAV:}authenticated continue; } $principals[] = $ace['principal']; } $properties = $this->server->getPropertiesForMultiplePaths($principals, $report->properties); $this->server->httpResponse->setStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->setBody($this->server->generateMultiStatus($properties)); }
/** * This function handles the addressbook-query REPORT * * This report is used by the client to filter an addressbook based on a * complex query. * * @param \DOMNode $dom * @return void */ protected function addressbookQueryReport($dom) { $query = new AddressBookQueryParser($dom); $query->parse(); $depth = $this->server->getHTTPDepth(0); if ($depth == 0) { $candidateNodes = [$this->server->tree->getNodeForPath($this->server->getRequestUri())]; if (!$candidateNodes[0] instanceof ICard) { throw new ReportNotSupported('The addressbook-query report is not supported on this url with Depth: 0'); } } else { $candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri()); } $xpath = new \DOMXPath($dom); $xpath->registerNameSpace('card', Plugin::NS_CARDDAV); $xpath->registerNameSpace('dav', 'urn:DAV'); $contentType = $xpath->evaluate("string(/card:addressbook-query/dav:prop/card:address-data/@content-type)"); $version = $xpath->evaluate("string(/card:addressbook-query/dav:prop/card:address-data/@version)"); if ($version) { $contentType .= '; version=' . $version; } $vcardType = $this->negotiateVCard($contentType); $validNodes = []; foreach ($candidateNodes as $node) { if (!$node instanceof ICard) { continue; } $blob = $node->get(); if (is_resource($blob)) { $blob = stream_get_contents($blob); } if (!$this->validateFilters($blob, $query->filters, $query->test)) { continue; } $validNodes[] = $node; if ($query->limit && $query->limit <= count($validNodes)) { // We hit the maximum number of items, we can stop now. break; } } $result = []; foreach ($validNodes as $validNode) { if ($depth == 0) { $href = $this->server->getRequestUri(); } else { $href = $this->server->getRequestUri() . '/' . $validNode->getName(); } list($props) = $this->server->getPropertiesForPath($href, $query->requestedProperties, 0); if (isset($props[200]['{' . self::NS_CARDDAV . '}address-data'])) { $props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard($props[200]['{' . self::NS_CARDDAV . '}address-data'], $vcardType); } $result[] = $props; } $prefer = $this->server->getHTTPPRefer(); $this->server->httpResponse->setStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer'); $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return-minimal'])); }
/** * 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; }
/** * principalPropertySearchReport * * This method is responsible for handing the * {DAV:}principal-property-search report. This report can be used for * clients to search for groups of principals, based on the value of one * or more properties. * * @param \DOMDocument $dom * @return void */ protected function principalPropertySearchReport(\DOMDocument $dom) { list($searchProperties, $requestedProperties, $applyToPrincipalCollectionSet, $test) = $this->parsePrincipalPropertySearchReportRequest($dom); $uri = null; if (!$applyToPrincipalCollectionSet) { $uri = $this->server->getRequestUri(); } $result = $this->principalSearch($searchProperties, $requestedProperties, $uri, $test); $prefer = $this->server->getHTTPPRefer(); $this->server->httpResponse->setStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer'); $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return-minimal'])); }
/** * 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 string $tempLocation * @param string $uri * @return bool */ public function httpPropfind($tempLocation, $uri) { if (!file_exists($tempLocation)) { return true; } $hR = $this->server->httpResponse; $hR->setHeader('X-Sabre-Temp', 'true'); $hR->sendStatus(207); $hR->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->parsePropFindRequest($this->server->httpRequest->getBody(true)); $properties = array('href' => $uri, 200 => array('{DAV:}getlastmodified' => new Property\GetLastModified(filemtime($tempLocation)), '{DAV:}getcontentlength' => filesize($tempLocation), '{DAV:}resourcetype' => new Property\ResourceType(null), '{' . Server::NS_SABREDAV . '}tempFile' => true)); $data = $this->server->generateMultiStatus(array($properties)); $hR->sendBody($data); return false; }
/** * principalPropertySearchReport * * This method is responsible for handing the * {DAV:}principal-property-search report. This report can be used for * clients to search for groups of principals, based on the value of one * or more properties. * * @param Xml\Request\PrincipalPropertySearchReport $report * @return void */ protected function principalPropertySearchReport($report) { $uri = null; if (!$report->applyToPrincipalCollectionSet) { $uri = $this->server->httpRequest->getPath(); } if ($this->server->getHttpDepth('0') !== 0) { throw new BadRequest('Depth must be 0'); } $result = $this->principalSearch($report->searchProperties, $report->properties, $uri, $report->test); $prefer = $this->server->getHTTPPrefer(); $this->server->httpResponse->setStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer'); $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return'] === 'minimal')); }
/** * This function handles the addressbook-query REPORT * * This report is used by the client to filter an addressbook based on a * complex query. * * @param \DOMNode $dom * @return void */ protected function addressbookQueryReport($dom) { $query = new AddressBookQueryParser($dom); $query->parse(); $depth = $this->server->getHTTPDepth(0); if ($depth == 0) { $candidateNodes = array($this->server->tree->getNodeForPath($this->server->getRequestUri())); } else { $candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri()); } $validNodes = array(); foreach ($candidateNodes as $node) { if (!$node instanceof ICard) { continue; } $blob = $node->get(); if (is_resource($blob)) { $blob = stream_get_contents($blob); } if (!$this->validateFilters($blob, $query->filters, $query->test)) { continue; } $validNodes[] = $node; if ($query->limit && $query->limit <= count($validNodes)) { // We hit the maximum number of items, we can stop now. break; } } $result = array(); foreach ($validNodes as $validNode) { if ($depth == 0) { $href = $this->server->getRequestUri(); } else { $href = $this->server->getRequestUri() . '/' . $validNode->getName(); } list($result[]) = $this->server->getPropertiesForPath($href, $query->requestedProperties, 0); } $prefer = $this->server->getHTTPPRefer(); $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer'); $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal'])); }