diff options
author | Vincent Petry <pvince81@owncloud.com> | 2015-02-12 12:29:01 +0100 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2015-02-23 22:27:23 +0100 |
commit | 9f6dcb9d3e2f43f336dafeb739e04ba9614d9b5f (patch) | |
tree | fa72017a9bf76c526ddb3dfe0969f0584a4a7d67 /lib/private/connector/sabre/filesplugin.php | |
parent | 66e3211fd8a57b0fb296d1dcc980272721e9f99d (diff) | |
download | nextcloud-server-9f6dcb9d3e2f43f336dafeb739e04ba9614d9b5f.tar.gz nextcloud-server-9f6dcb9d3e2f43f336dafeb739e04ba9614d9b5f.zip |
Sabre Update to 2.1
- VObject fixes for Sabre\VObject 3.3
- Remove VObject property workarounds
- Added prefetching for tags in sabre tags plugin
- Moved oc_properties logic to separate PropertyStorage backend (WIP)
- Fixed Sabre connector namespaces
- Improved files plugin to handle props on-demand
- Moved allowed props from server class to files plugin
- Fixed tags caching for files that are known to have no tags
(less queries)
- Added/fixed unit tests for Sabre FilesPlugin, TagsPlugin
- Replace OC\Connector\Sabre\Request with direct call to
httpRequest->setUrl()
- Fix exception detection in DAV client when using Sabre\DAV\Client
- Added setETag() on Node instead of using the static FileSystem
- Also preload tags/props when depth is infinity
Diffstat (limited to 'lib/private/connector/sabre/filesplugin.php')
-rw-r--r-- | lib/private/connector/sabre/filesplugin.php | 179 |
1 files changed, 112 insertions, 67 deletions
diff --git a/lib/private/connector/sabre/filesplugin.php b/lib/private/connector/sabre/filesplugin.php index d62f4e4ce53..1932dabd393 100644 --- a/lib/private/connector/sabre/filesplugin.php +++ b/lib/private/connector/sabre/filesplugin.php @@ -1,30 +1,21 @@ <?php -/** - * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ -class OC_Connector_Sabre_FilesPlugin extends \Sabre\DAV\ServerPlugin -{ +namespace OC\Connector\Sabre; + +use \Sabre\DAV\PropFind; +use \Sabre\DAV\PropPatch; +use \Sabre\HTTP\RequestInterface; +use \Sabre\HTTP\ResponseInterface; + +class FilesPlugin extends \Sabre\DAV\ServerPlugin { // namespace const NS_OWNCLOUD = 'http://owncloud.org/ns'; + const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id'; + const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions'; + const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL'; + const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size'; + const GETETAG_PROPERTYNAME = '{DAV:}getetag'; + const GETLASTMODIFIED_PROPERTYNAME = '{DAV:}getlastmodified'; /** * Reference to main server object @@ -34,6 +25,15 @@ class OC_Connector_Sabre_FilesPlugin extends \Sabre\DAV\ServerPlugin private $server; /** + * @var \Sabre\DAV\Tree + */ + private $tree; + + public function __construct(\Sabre\DAV\Tree $tree) { + $this->tree = $tree; + } + + /** * This initializes the plugin. * * This function is called by \Sabre\DAV\Server, after @@ -47,69 +47,101 @@ class OC_Connector_Sabre_FilesPlugin extends \Sabre\DAV\ServerPlugin public function initialize(\Sabre\DAV\Server $server) { $server->xmlNamespaces[self::NS_OWNCLOUD] = 'oc'; - $server->protectedProperties[] = '{' . self::NS_OWNCLOUD . '}id'; - $server->protectedProperties[] = '{' . self::NS_OWNCLOUD . '}permissions'; - $server->protectedProperties[] = '{' . self::NS_OWNCLOUD . '}size'; - $server->protectedProperties[] = '{' . self::NS_OWNCLOUD . '}downloadURL'; + $server->protectedProperties[] = self::FILEID_PROPERTYNAME; + $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME; + $server->protectedProperties[] = self::SIZE_PROPERTYNAME; + $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME; + + // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH + $allowedProperties = ['{DAV:}getetag', '{DAV:}getlastmodified']; + $server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties); $this->server = $server; - $this->server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); - $this->server->subscribeEvent('afterBind', array($this, 'sendFileIdHeader')); - $this->server->subscribeEvent('afterWriteContent', array($this, 'sendFileIdHeader')); + $this->server->on('propFind', array($this, 'handleGetProperties')); + $this->server->on('propPatch', array($this, 'handleUpdateProperties')); + $this->server->on('afterBind', array($this, 'sendFileIdHeader')); + $this->server->on('afterWriteContent', array($this, 'sendFileIdHeader')); + $this->server->on('beforeMethod:GET', array($this, 'handleRangeHeaders')); } /** * Adds all ownCloud-specific properties * - * @param string $path + * @param PropFind $propFind * @param \Sabre\DAV\INode $node - * @param array $requestedProperties - * @param array $returnedProperties * @return void */ - public function beforeGetProperties($path, \Sabre\DAV\INode $node, array &$requestedProperties, array &$returnedProperties) { + public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) { - if ($node instanceof OC_Connector_Sabre_Node) { + if ($node instanceof \OC\Connector\Sabre\Node) { - $fileIdPropertyName = '{' . self::NS_OWNCLOUD . '}id'; - $permissionsPropertyName = '{' . self::NS_OWNCLOUD . '}permissions'; - if (array_search($fileIdPropertyName, $requestedProperties)) { - unset($requestedProperties[array_search($fileIdPropertyName, $requestedProperties)]); - } - if (array_search($permissionsPropertyName, $requestedProperties)) { - unset($requestedProperties[array_search($permissionsPropertyName, $requestedProperties)]); - } + $propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) { + return $node->getFileId(); + }); - /** @var $node OC_Connector_Sabre_Node */ - $fileId = $node->getFileId(); - if (!is_null($fileId)) { - $returnedProperties[200][$fileIdPropertyName] = $fileId; - } + $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) { + return $node->getDavPermissions(); + }); - $permissions = $node->getDavPermissions(); - if (!is_null($permissions)) { - $returnedProperties[200][$permissionsPropertyName] = $permissions; - } + $propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) { + return $node->getEtag(); + }); } - if ($node instanceof OC_Connector_Sabre_File) { - /** @var $node OC_Connector_Sabre_File */ - $directDownloadUrl = $node->getDirectDownload(); - if (isset($directDownloadUrl['url'])) { - $directDownloadUrlPropertyName = '{' . self::NS_OWNCLOUD . '}downloadURL'; - $returnedProperties[200][$directDownloadUrlPropertyName] = $directDownloadUrl['url']; - } + if ($node instanceof \OC\Connector\Sabre\File) { + $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) { + /** @var $node \OC\Connector\Sabre\File */ + $directDownloadUrl = $node->getDirectDownload(); + if (isset($directDownloadUrl['url'])) { + return $directDownloadUrl['url']; + } + return false; + }); } - if ($node instanceof OC_Connector_Sabre_Directory) { - $sizePropertyName = '{' . self::NS_OWNCLOUD . '}size'; - - /** @var $node OC_Connector_Sabre_Directory */ - $returnedProperties[200][$sizePropertyName] = $node->getSize(); + if ($node instanceof \OC\Connector\Sabre\Directory) { + $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) { + return $node->getSize(); + }); } } /** + * Update ownCloud-specific properties + * + * @param string $path + * @param PropPatch $propPatch + * + * @return void + */ + public function handleUpdateProperties($path, PropPatch $propPatch) { + $propPatch->handle(self::GETLASTMODIFIED_PROPERTYNAME, function($time) use ($path) { + if (empty($time)) { + return false; + } + $node = $this->tree->getNodeForPath($path); + if (is_null($node)) { + return 404; + } + $node->touch($time); + return true; + }); + $propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($path) { + if (empty($etag)) { + return false; + } + $node = $this->tree->getNodeForPath($path); + if (is_null($node)) { + return 404; + } + if ($node->setEtag($etag) !== -1) { + return true; + } + return false; + }); + } + + /** * @param string $filePath * @param \Sabre\DAV\INode $node * @throws \Sabre\DAV\Exception\BadRequest @@ -117,8 +149,8 @@ class OC_Connector_Sabre_FilesPlugin extends \Sabre\DAV\ServerPlugin public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) { // chunked upload handling if (isset($_SERVER['HTTP_OC_CHUNKED'])) { - list($path, $name) = \Sabre\DAV\URLUtil::splitPath($filePath); - $info = OC_FileChunking::decodeName($name); + list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath); + $info = \OC_FileChunking::decodeName($name); if (!empty($info)) { $filePath = $path . '/' . $info['name']; } @@ -129,7 +161,7 @@ class OC_Connector_Sabre_FilesPlugin extends \Sabre\DAV\ServerPlugin return; } $node = $this->server->tree->getNodeForPath($filePath); - if ($node instanceof OC_Connector_Sabre_Node) { + if ($node instanceof \OC\Connector\Sabre\Node) { $fileId = $node->getFileId(); if (!is_null($fileId)) { $this->server->httpResponse->setHeader('OC-FileId', $fileId); @@ -137,4 +169,17 @@ class OC_Connector_Sabre_FilesPlugin extends \Sabre\DAV\ServerPlugin } } + /** + * Remove range headers if encryption is enabled. + * + * @param RequestInterface $request + * @param ResponseInterface $response + */ + public function handleRangeHeaders(RequestInterface $request, ResponseInterface $response) { + if (\OC_App::isEnabled('files_encryption')) { + // encryption does not support range requests (yet) + $request->removeHeader('range'); + } + } + } |