/** * Patch an uri * * The WebDAV patch request can be used to modify only a part of an * existing resource. If the resource does not exist yet and the first * offset is not 0, the request fails * * @param string $uri * @return void */ protected function httpPatch($uri) { // Get the node. Will throw a 404 if not found $node = $this->server->tree->getNodeForPath($uri); if (!$node instanceof IFile) { throw new DAV\Exception\MethodNotAllowed('The target resource does not support the PATCH method.'); } $range = $this->getHTTPUpdateRange(); if (!$range) { throw new DAV\Exception\BadRequest('No valid "X-Update-Range" found in the headers'); } $contentType = strtolower($this->server->httpRequest->getHeader('Content-Type')); if ($contentType != 'application/x-sabredav-partialupdate') { throw new DAV\Exception\UnsupportedMediaType('Unknown Content-Type header "' . $contentType . '"'); } $len = $this->server->httpRequest->getHeader('Content-Length'); // Load the begin and end data $start = $range[0] ? $range[0] : 0; $end = $range[1] ? $range[1] : $len - 1; // Check consistency if ($end < $start) { throw new DAV\Exception\RequestedRangeNotSatisfiable('The end offset (' . $range[1] . ') is lower than the start offset (' . $range[0] . ')'); } if ($end - $start + 1 != $len) { throw new DAV\Exception\RequestedRangeNotSatisfiable('Actual data length (' . $len . ') is not consistent with begin (' . $range[0] . ') and end (' . $range[1] . ') offsets'); } // Checking If-None-Match and related headers. if (!$this->server->checkPreconditions()) { return; } if (!$this->server->broadcastEvent('beforeWriteContent', array($uri, $node, null))) { return; } $body = $this->server->httpRequest->getBody(); $etag = $node->putRange($body, $start - 1); $this->server->broadcastEvent('afterWriteContent', array($uri, $node)); $this->server->httpResponse->setHeader('Content-Length', '0'); if ($etag) { $this->server->httpResponse->setHeader('ETag', $etag); } $this->server->httpResponse->sendStatus(204); return false; }