summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/connector/sabre
diff options
context:
space:
mode:
authorJoas Schilling <nickvergessen@gmx.de>2016-05-12 09:42:40 +0200
committerThomas Müller <DeepDiver1975@users.noreply.github.com>2016-05-12 09:42:40 +0200
commitdd9ee10bc0699e5dcc17c3ef2181dcda01d9a69b (patch)
tree2d464fcc20ea330481e56487287aeae462ce5917 /apps/dav/lib/connector/sabre
parent4a3311f430ec6e45c62b2ebde2cae71e943f3c81 (diff)
downloadnextcloud-server-dd9ee10bc0699e5dcc17c3ef2181dcda01d9a69b.tar.gz
nextcloud-server-dd9ee10bc0699e5dcc17c3ef2181dcda01d9a69b.zip
Move dav app to PSR-4 (#24527)
* Move Application to correct namespace and PSR-4 it * Move dav app to PSR-4
Diffstat (limited to 'apps/dav/lib/connector/sabre')
-rw-r--r--apps/dav/lib/connector/sabre/appenabledplugin.php90
-rw-r--r--apps/dav/lib/connector/sabre/auth.php229
-rw-r--r--apps/dav/lib/connector/sabre/blocklegacyclientplugin.php80
-rw-r--r--apps/dav/lib/connector/sabre/checksumlist.php71
-rw-r--r--apps/dav/lib/connector/sabre/commentpropertiesplugin.php130
-rw-r--r--apps/dav/lib/connector/sabre/copyetagheaderplugin.php57
-rw-r--r--apps/dav/lib/connector/sabre/custompropertiesbackend.php355
-rw-r--r--apps/dav/lib/connector/sabre/davaclplugin.php72
-rw-r--r--apps/dav/lib/connector/sabre/directory.php310
-rw-r--r--apps/dav/lib/connector/sabre/dummygetresponseplugin.php70
-rw-r--r--apps/dav/lib/connector/sabre/exception/entitytoolarge.php44
-rw-r--r--apps/dav/lib/connector/sabre/exception/filelocked.php48
-rw-r--r--apps/dav/lib/connector/sabre/exception/forbidden.php64
-rw-r--r--apps/dav/lib/connector/sabre/exception/invalidpath.php77
-rw-r--r--apps/dav/lib/connector/sabre/exception/unsupportedmediatype.php44
-rw-r--r--apps/dav/lib/connector/sabre/exceptionloggerplugin.php111
-rw-r--r--apps/dav/lib/connector/sabre/fakelockerplugin.php156
-rw-r--r--apps/dav/lib/connector/sabre/file.php567
-rw-r--r--apps/dav/lib/connector/sabre/filesplugin.php398
-rw-r--r--apps/dav/lib/connector/sabre/filesreportplugin.php333
-rw-r--r--apps/dav/lib/connector/sabre/lockplugin.php84
-rw-r--r--apps/dav/lib/connector/sabre/maintenanceplugin.php92
-rw-r--r--apps/dav/lib/connector/sabre/node.php348
-rw-r--r--apps/dav/lib/connector/sabre/objecttree.php297
-rw-r--r--apps/dav/lib/connector/sabre/principal.php234
-rw-r--r--apps/dav/lib/connector/sabre/quotaplugin.php146
-rw-r--r--apps/dav/lib/connector/sabre/server.php44
-rw-r--r--apps/dav/lib/connector/sabre/serverfactory.php184
-rw-r--r--apps/dav/lib/connector/sabre/sharesplugin.php177
-rw-r--r--apps/dav/lib/connector/sabre/sharetypelist.php87
-rw-r--r--apps/dav/lib/connector/sabre/taglist.php120
-rw-r--r--apps/dav/lib/connector/sabre/tagsplugin.php293
32 files changed, 0 insertions, 5412 deletions
diff --git a/apps/dav/lib/connector/sabre/appenabledplugin.php b/apps/dav/lib/connector/sabre/appenabledplugin.php
deleted file mode 100644
index cb061d6a309..00000000000
--- a/apps/dav/lib/connector/sabre/appenabledplugin.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\App\IAppManager;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\ServerPlugin;
-
-/**
- * Plugin to check if an app is enabled for the current user
- */
-class AppEnabledPlugin extends ServerPlugin {
-
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var string
- */
- private $app;
-
- /**
- * @var \OCP\App\IAppManager
- */
- private $appManager;
-
- /**
- * @param string $app
- * @param \OCP\App\IAppManager $appManager
- */
- public function __construct($app, IAppManager $appManager) {
- $this->app = $app;
- $this->appManager = $appManager;
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
-
- $this->server = $server;
- $this->server->on('beforeMethod', array($this, 'checkAppEnabled'), 30);
- }
-
- /**
- * This method is called before any HTTP after auth and checks if the user has access to the app
- *
- * @throws \Sabre\DAV\Exception\Forbidden
- * @return bool
- */
- public function checkAppEnabled() {
- if (!$this->appManager->isEnabledForUser($this->app)) {
- throw new Forbidden();
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php
deleted file mode 100644
index b8047e779f5..00000000000
--- a/apps/dav/lib/connector/sabre/auth.php
+++ /dev/null
@@ -1,229 +0,0 @@
-<?php
-/**
- * @author Arthur Schiwon <blizzz@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Markus Goetz <markus@woboq.com>
- * @author Michael Gapczynski <GapczynskiM@gmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre;
-
-use Exception;
-use OC\AppFramework\Http\Request;
-use OCP\IRequest;
-use OCP\ISession;
-use OC\User\Session;
-use Sabre\DAV\Auth\Backend\AbstractBasic;
-use Sabre\DAV\Exception\NotAuthenticated;
-use Sabre\DAV\Exception\ServiceUnavailable;
-use Sabre\HTTP\RequestInterface;
-use Sabre\HTTP\ResponseInterface;
-
-class Auth extends AbstractBasic {
- const DAV_AUTHENTICATED = 'AUTHENTICATED_TO_DAV_BACKEND';
-
- /** @var ISession */
- private $session;
- /** @var Session */
- private $userSession;
- /** @var IRequest */
- private $request;
- /** @var string */
- private $currentUser;
-
- /**
- * @param ISession $session
- * @param Session $userSession
- * @param IRequest $request
- * @param string $principalPrefix
- */
- public function __construct(ISession $session,
- Session $userSession,
- IRequest $request,
- $principalPrefix = 'principals/users/') {
- $this->session = $session;
- $this->userSession = $userSession;
- $this->request = $request;
- $this->principalPrefix = $principalPrefix;
- }
-
- /**
- * Whether the user has initially authenticated via DAV
- *
- * This is required for WebDAV clients that resent the cookies even when the
- * account was changed.
- *
- * @see https://github.com/owncloud/core/issues/13245
- *
- * @param string $username
- * @return bool
- */
- public function isDavAuthenticated($username) {
- return !is_null($this->session->get(self::DAV_AUTHENTICATED)) &&
- $this->session->get(self::DAV_AUTHENTICATED) === $username;
- }
-
- /**
- * Validates a username and password
- *
- * This method should return true or false depending on if login
- * succeeded.
- *
- * @param string $username
- * @param string $password
- * @return bool
- */
- protected function validateUserPass($username, $password) {
- if ($this->userSession->isLoggedIn() &&
- $this->isDavAuthenticated($this->userSession->getUser()->getUID())
- ) {
- \OC_Util::setupFS($this->userSession->getUser()->getUID());
- $this->session->close();
- return true;
- } else {
- \OC_Util::setUpFS(); //login hooks may need early access to the filesystem
- if($this->userSession->login($username, $password)) {
- $this->userSession->createSessionToken($this->request, $username, $password);
- \OC_Util::setUpFS($this->userSession->getUser()->getUID());
- $this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID());
- $this->session->close();
- return true;
- } else {
- $this->session->close();
- return false;
- }
- }
- }
-
- /**
- * @param RequestInterface $request
- * @param ResponseInterface $response
- * @return array
- * @throws NotAuthenticated
- * @throws ServiceUnavailable
- */
- function check(RequestInterface $request, ResponseInterface $response) {
- try {
- $result = $this->auth($request, $response);
- return $result;
- } catch (NotAuthenticated $e) {
- throw $e;
- } catch (Exception $e) {
- $class = get_class($e);
- $msg = $e->getMessage();
- throw new ServiceUnavailable("$class: $msg");
- }
- }
-
- /**
- * Checks whether a CSRF check is required on the request
- *
- * @return bool
- */
- private function requiresCSRFCheck() {
- // GET requires no check at all
- if($this->request->getMethod() === 'GET') {
- return false;
- }
-
- // Official ownCloud clients require no checks
- if($this->request->isUserAgent([
- Request::USER_AGENT_OWNCLOUD_DESKTOP,
- Request::USER_AGENT_OWNCLOUD_ANDROID,
- Request::USER_AGENT_OWNCLOUD_IOS,
- ])) {
- return false;
- }
-
- // If not logged-in no check is required
- if(!$this->userSession->isLoggedIn()) {
- return false;
- }
-
- // POST always requires a check
- if($this->request->getMethod() === 'POST') {
- return true;
- }
-
- // If logged-in AND DAV authenticated no check is required
- if($this->userSession->isLoggedIn() &&
- $this->isDavAuthenticated($this->userSession->getUser()->getUID())) {
- return false;
- }
-
- return true;
- }
-
- /**
- * @param RequestInterface $request
- * @param ResponseInterface $response
- * @return array
- * @throws NotAuthenticated
- */
- private function auth(RequestInterface $request, ResponseInterface $response) {
- $forcedLogout = false;
- if(!$this->request->passesCSRFCheck() &&
- $this->requiresCSRFCheck()) {
- // In case of a fail with POST we need to recheck the credentials
- if($this->request->getMethod() === 'POST') {
- $forcedLogout = true;
- } else {
- $response->setStatus(401);
- throw new \Sabre\DAV\Exception\NotAuthenticated('CSRF check not passed.');
- }
- }
-
- if($forcedLogout) {
- $this->userSession->logout();
- } else {
- if (\OC_User::handleApacheAuth() ||
- //Fix for broken webdav clients
- ($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED))) ||
- //Well behaved clients that only send the cookie are allowed
- ($this->userSession->isLoggedIn() && $this->session->get(self::DAV_AUTHENTICATED) === $this->userSession->getUser()->getUID() && $request->getHeader('Authorization') === null)
- ) {
- $user = $this->userSession->getUser()->getUID();
- \OC_Util::setupFS($user);
- $this->currentUser = $user;
- $this->session->close();
- return [true, $this->principalPrefix . $user];
- }
- }
-
- if (!$this->userSession->isLoggedIn() && in_array('XMLHttpRequest', explode(',', $request->getHeader('X-Requested-With')))) {
- // do not re-authenticate over ajax, use dummy auth name to prevent browser popup
- $response->addHeader('WWW-Authenticate','DummyBasic realm="' . $this->realm . '"');
- $response->setStatus(401);
- throw new \Sabre\DAV\Exception\NotAuthenticated('Cannot authenticate over ajax calls');
- }
-
- $data = parent::check($request, $response);
- if($data[0] === true) {
- $startPos = strrpos($data[1], '/') + 1;
- $user = $this->userSession->getUser()->getUID();
- $data[1] = substr_replace($data[1], $user, $startPos);
- }
- return $data;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/blocklegacyclientplugin.php b/apps/dav/lib/connector/sabre/blocklegacyclientplugin.php
deleted file mode 100644
index 70d19cb7f2a..00000000000
--- a/apps/dav/lib/connector/sabre/blocklegacyclientplugin.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\IConfig;
-use Sabre\HTTP\RequestInterface;
-use Sabre\DAV\ServerPlugin;
-use Sabre\DAV\Exception;
-
-/**
- * Class BlockLegacyClientPlugin is used to detect old legacy sync clients and
- * returns a 403 status to those clients
- *
- * @package OCA\DAV\Connector\Sabre
- */
-class BlockLegacyClientPlugin extends ServerPlugin {
- /** @var \Sabre\DAV\Server */
- protected $server;
- /** @var IConfig */
- protected $config;
-
- /**
- * @param IConfig $config
- */
- public function __construct(IConfig $config) {
- $this->config = $config;
- }
-
- /**
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
- $this->server = $server;
- $this->server->on('beforeMethod', [$this, 'beforeHandler'], 200);
- }
-
- /**
- * Detects all unsupported clients and throws a \Sabre\DAV\Exception\Forbidden
- * exception which will result in a 403 to them.
- * @param RequestInterface $request
- * @throws \Sabre\DAV\Exception\Forbidden If the client version is not supported
- */
- public function beforeHandler(RequestInterface $request) {
- $userAgent = $request->getHeader('User-Agent');
- if($userAgent === null) {
- return;
- }
-
- $minimumSupportedDesktopVersion = $this->config->getSystemValue('minimum.supported.desktop.version', '1.7.0');
-
- // Match on the mirall version which is in scheme "Mozilla/5.0 (%1) mirall/%2" or
- // "mirall/%1" for older releases
- preg_match("/(?:mirall\\/)([\d.]+)/i", $userAgent, $versionMatches);
- if(isset($versionMatches[1]) &&
- version_compare($versionMatches[1], $minimumSupportedDesktopVersion) === -1) {
- throw new \Sabre\DAV\Exception\Forbidden('Unsupported client version.');
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/checksumlist.php b/apps/dav/lib/connector/sabre/checksumlist.php
deleted file mode 100644
index f137222acca..00000000000
--- a/apps/dav/lib/connector/sabre/checksumlist.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre;
-
-use Sabre\Xml\XmlSerializable;
-use Sabre\Xml\Element;
-use Sabre\Xml\Writer;
-
-/**
- * Checksumlist property
- *
- * This property contains multiple "checksum" elements, each containing a
- * checksum name.
- */
-class ChecksumList implements XmlSerializable {
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
-
- /** @var string[] of TYPE:CHECKSUM */
- private $checksums;
-
- /**
- * @param string $checksum
- */
- public function __construct($checksum) {
- $this->checksums = explode(',', $checksum);
- }
-
- /**
- * The xmlSerialize metod is called during xml writing.
- *
- * Use the $writer argument to write its own xml serialization.
- *
- * An important note: do _not_ create a parent element. Any element
- * implementing XmlSerializble should only ever write what's considered
- * its 'inner xml'.
- *
- * The parent of the current element is responsible for writing a
- * containing element.
- *
- * This allows serializers to be re-used for different element names.
- *
- * If you are opening new elements, you must also close them again.
- *
- * @param Writer $writer
- * @return void
- */
- function xmlSerialize(Writer $writer) {
-
- foreach ($this->checksums as $checksum) {
- $writer->writeElement('{' . self::NS_OWNCLOUD . '}checksum', $checksum);
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/commentpropertiesplugin.php b/apps/dav/lib/connector/sabre/commentpropertiesplugin.php
deleted file mode 100644
index a8d5f771122..00000000000
--- a/apps/dav/lib/connector/sabre/commentpropertiesplugin.php
+++ /dev/null
@@ -1,130 +0,0 @@
-<?php
-/**
- * @author Arthur Schiwon <blizzz@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\Comments\ICommentsManager;
-use OCP\IUserSession;
-use Sabre\DAV\PropFind;
-use Sabre\DAV\ServerPlugin;
-
-class CommentPropertiesPlugin extends ServerPlugin {
-
- const PROPERTY_NAME_HREF = '{http://owncloud.org/ns}comments-href';
- const PROPERTY_NAME_COUNT = '{http://owncloud.org/ns}comments-count';
- const PROPERTY_NAME_UNREAD = '{http://owncloud.org/ns}comments-unread';
-
- /** @var \Sabre\DAV\Server */
- protected $server;
-
- /** @var ICommentsManager */
- private $commentsManager;
-
- /** @var IUserSession */
- private $userSession;
-
- public function __construct(ICommentsManager $commentsManager, IUserSession $userSession) {
- $this->commentsManager = $commentsManager;
- $this->userSession = $userSession;
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- function initialize(\Sabre\DAV\Server $server) {
- $this->server = $server;
- $this->server->on('propFind', array($this, 'handleGetProperties'));
- }
-
- /**
- * Adds tags and favorites properties to the response,
- * if requested.
- *
- * @param PropFind $propFind
- * @param \Sabre\DAV\INode $node
- * @return void
- */
- public function handleGetProperties(
- PropFind $propFind,
- \Sabre\DAV\INode $node
- ) {
- if (!($node instanceof File) && !($node instanceof Directory)) {
- return;
- }
-
- $propFind->handle(self::PROPERTY_NAME_COUNT, function() use ($node) {
- return $this->commentsManager->getNumberOfCommentsForObject('files', strval($node->getId()));
- });
-
- $propFind->handle(self::PROPERTY_NAME_HREF, function() use ($node) {
- return $this->getCommentsLink($node);
- });
-
- $propFind->handle(self::PROPERTY_NAME_UNREAD, function() use ($node) {
- return $this->getUnreadCount($node);
- });
- }
-
- /**
- * returns a reference to the comments node
- *
- * @param Node $node
- * @return mixed|string
- */
- public function getCommentsLink(Node $node) {
- $href = $this->server->getBaseUri();
- $entryPoint = strrpos($href, '/webdav/');
- if($entryPoint === false) {
- // in case we end up somewhere else, unexpectedly.
- return null;
- }
- $href = substr_replace($href, '/dav/', $entryPoint);
- $href .= 'comments/files/' . rawurldecode($node->getId());
- return $href;
- }
-
- /**
- * returns the number of unread comments for the currently logged in user
- * on the given file or directory node
- *
- * @param Node $node
- * @return Int|null
- */
- public function getUnreadCount(Node $node) {
- $user = $this->userSession->getUser();
- if(is_null($user)) {
- return null;
- }
-
- $lastRead = $this->commentsManager->getReadMark('files', strval($node->getId()), $user);
-
- return $this->commentsManager->getNumberOfCommentsForObject('files', strval($node->getId()), $lastRead);
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/copyetagheaderplugin.php b/apps/dav/lib/connector/sabre/copyetagheaderplugin.php
deleted file mode 100644
index 49b6a7b2de7..00000000000
--- a/apps/dav/lib/connector/sabre/copyetagheaderplugin.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-/**
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use \Sabre\HTTP\RequestInterface;
-use \Sabre\HTTP\ResponseInterface;
-
-/**
- * Copies the "Etag" header to "OC-Etag" after any request.
- * This is a workaround for setups that automatically strip
- * or mangle Etag headers.
- */
-class CopyEtagHeaderPlugin extends \Sabre\DAV\ServerPlugin {
- /**
- * This initializes the plugin.
- *
- * @param \Sabre\DAV\Server $server Sabre server
- *
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
- $server->on('afterMethod', array($this, 'afterMethod'));
- }
-
- /**
- * After method, copy the "Etag" header to "OC-Etag" header.
- *
- * @param RequestInterface $request request
- * @param ResponseInterface $response response
- */
- public function afterMethod(RequestInterface $request, ResponseInterface $response) {
- $eTag = $response->getHeader('Etag');
- if (!empty($eTag)) {
- $response->setHeader('OC-ETag', $eTag);
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/custompropertiesbackend.php b/apps/dav/lib/connector/sabre/custompropertiesbackend.php
deleted file mode 100644
index 5946c9910d4..00000000000
--- a/apps/dav/lib/connector/sabre/custompropertiesbackend.php
+++ /dev/null
@@ -1,355 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\IDBConnection;
-use OCP\IUser;
-use Sabre\DAV\PropertyStorage\Backend\BackendInterface;
-use Sabre\DAV\PropFind;
-use Sabre\DAV\PropPatch;
-use Sabre\DAV\Tree;
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\Exception\ServiceUnavailable;
-
-class CustomPropertiesBackend implements BackendInterface {
-
- /**
- * Ignored properties
- *
- * @var array
- */
- private $ignoredProperties = array(
- '{DAV:}getcontentlength',
- '{DAV:}getcontenttype',
- '{DAV:}getetag',
- '{DAV:}quota-used-bytes',
- '{DAV:}quota-available-bytes',
- '{DAV:}quota-available-bytes',
- '{http://owncloud.org/ns}permissions',
- '{http://owncloud.org/ns}downloadURL',
- '{http://owncloud.org/ns}dDC',
- '{http://owncloud.org/ns}size',
- );
-
- /**
- * @var Tree
- */
- private $tree;
-
- /**
- * @var IDBConnection
- */
- private $connection;
-
- /**
- * @var IUser
- */
- private $user;
-
- /**
- * Properties cache
- *
- * @var array
- */
- private $cache = [];
-
- /**
- * @param Tree $tree node tree
- * @param IDBConnection $connection database connection
- * @param IUser $user owner of the tree and properties
- */
- public function __construct(
- Tree $tree,
- IDBConnection $connection,
- IUser $user) {
- $this->tree = $tree;
- $this->connection = $connection;
- $this->user = $user->getUID();
- }
-
- /**
- * Fetches properties for a path.
- *
- * @param string $path
- * @param PropFind $propFind
- * @return void
- */
- public function propFind($path, PropFind $propFind) {
- try {
- $node = $this->tree->getNodeForPath($path);
- if (!($node instanceof Node)) {
- return;
- }
- } catch (ServiceUnavailable $e) {
- // might happen for unavailable mount points, skip
- return;
- } catch (NotFound $e) {
- // in some rare (buggy) cases the node might not be found,
- // we catch the exception to prevent breaking the whole list with a 404
- // (soft fail)
- \OC::$server->getLogger()->warning(
- 'Could not get node for path: \"' . $path . '\" : ' . $e->getMessage(),
- array('app' => 'files')
- );
- return;
- }
-
- $requestedProps = $propFind->get404Properties();
-
- // these might appear
- $requestedProps = array_diff(
- $requestedProps,
- $this->ignoredProperties
- );
-
- if (empty($requestedProps)) {
- return;
- }
-
- if ($node instanceof Directory
- && $propFind->getDepth() !== 0
- ) {
- // note: pre-fetching only supported for depth <= 1
- $this->loadChildrenProperties($node, $requestedProps);
- }
-
- $props = $this->getProperties($node, $requestedProps);
- foreach ($props as $propName => $propValue) {
- $propFind->set($propName, $propValue);
- }
- }
-
- /**
- * Updates properties for a path
- *
- * @param string $path
- * @param PropPatch $propPatch
- *
- * @return void
- */
- public function propPatch($path, PropPatch $propPatch) {
- $node = $this->tree->getNodeForPath($path);
- if (!($node instanceof Node)) {
- return;
- }
-
- $propPatch->handleRemaining(function($changedProps) use ($node) {
- return $this->updateProperties($node, $changedProps);
- });
- }
-
- /**
- * This method is called after a node is deleted.
- *
- * @param string $path path of node for which to delete properties
- */
- public function delete($path) {
- $statement = $this->connection->prepare(
- 'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'
- );
- $statement->execute(array($this->user, '/' . $path));
- $statement->closeCursor();
-
- unset($this->cache[$path]);
- }
-
- /**
- * This method is called after a successful MOVE
- *
- * @param string $source
- * @param string $destination
- *
- * @return void
- */
- public function move($source, $destination) {
- $statement = $this->connection->prepare(
- 'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
- ' WHERE `userid` = ? AND `propertypath` = ?'
- );
- $statement->execute(array('/' . $destination, $this->user, '/' . $source));
- $statement->closeCursor();
- }
-
- /**
- * Returns a list of properties for this nodes.;
- * @param Node $node
- * @param array $requestedProperties requested properties or empty array for "all"
- * @return array
- * @note The properties list is a list of propertynames the client
- * requested, encoded as xmlnamespace#tagName, for example:
- * http://www.example.org/namespace#author If the array is empty, all
- * properties should be returned
- */
- private function getProperties(Node $node, array $requestedProperties) {
- $path = $node->getPath();
- if (isset($this->cache[$path])) {
- return $this->cache[$path];
- }
-
- // TODO: chunking if more than 1000 properties
- $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
-
- $whereValues = array($this->user, $path);
- $whereTypes = array(null, null);
-
- if (!empty($requestedProperties)) {
- // request only a subset
- $sql .= ' AND `propertyname` in (?)';
- $whereValues[] = $requestedProperties;
- $whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
- }
-
- $result = $this->connection->executeQuery(
- $sql,
- $whereValues,
- $whereTypes
- );
-
- $props = [];
- while ($row = $result->fetch()) {
- $props[$row['propertyname']] = $row['propertyvalue'];
- }
-
- $result->closeCursor();
-
- $this->cache[$path] = $props;
- return $props;
- }
-
- /**
- * Update properties
- *
- * @param Node $node node for which to update properties
- * @param array $properties array of properties to update
- *
- * @return bool
- */
- private function updateProperties($node, $properties) {
- $path = $node->getPath();
-
- $deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
- ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
-
- $insertStatement = 'INSERT INTO `*PREFIX*properties`' .
- ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
-
- $updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' .
- ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
-
- // TODO: use "insert or update" strategy ?
- $existing = $this->getProperties($node, array());
- $this->connection->beginTransaction();
- foreach ($properties as $propertyName => $propertyValue) {
- // If it was null, we need to delete the property
- if (is_null($propertyValue)) {
- if (array_key_exists($propertyName, $existing)) {
- $this->connection->executeUpdate($deleteStatement,
- array(
- $this->user,
- $path,
- $propertyName
- )
- );
- }
- } else {
- if (!array_key_exists($propertyName, $existing)) {
- $this->connection->executeUpdate($insertStatement,
- array(
- $this->user,
- $path,
- $propertyName,
- $propertyValue
- )
- );
- } else {
- $this->connection->executeUpdate($updateStatement,
- array(
- $propertyValue,
- $this->user,
- $path,
- $propertyName
- )
- );
- }
- }
- }
-
- $this->connection->commit();
- unset($this->cache[$path]);
-
- return true;
- }
-
- /**
- * Bulk load properties for directory children
- *
- * @param Directory $node
- * @param array $requestedProperties requested properties
- *
- * @return void
- */
- private function loadChildrenProperties(Directory $node, $requestedProperties) {
- $path = $node->getPath();
- if (isset($this->cache[$path])) {
- // we already loaded them at some point
- return;
- }
-
- $childNodes = $node->getChildren();
- // pre-fill cache
- foreach ($childNodes as $childNode) {
- $this->cache[$childNode->getPath()] = [];
- }
-
- $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` LIKE ?';
- $sql .= ' AND `propertyname` in (?) ORDER BY `propertypath`, `propertyname`';
-
- $result = $this->connection->executeQuery(
- $sql,
- array($this->user, rtrim($path, '/') . '/%', $requestedProperties),
- array(null, null, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
- );
-
- $oldPath = null;
- $props = [];
- while ($row = $result->fetch()) {
- $path = $row['propertypath'];
- if ($oldPath !== $path) {
- // save previously gathered props
- $this->cache[$oldPath] = $props;
- $oldPath = $path;
- // prepare props for next path
- $props = [];
- }
- $props[$row['propertyname']] = $row['propertyvalue'];
- }
- if (!is_null($oldPath)) {
- // save props from last run
- $this->cache[$oldPath] = $props;
- }
-
- $result->closeCursor();
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/davaclplugin.php b/apps/dav/lib/connector/sabre/davaclplugin.php
deleted file mode 100644
index f5699b469c3..00000000000
--- a/apps/dav/lib/connector/sabre/davaclplugin.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\IFile;
-use Sabre\DAV\INode;
-use \Sabre\DAV\PropFind;
-use \Sabre\DAV\PropPatch;
-use Sabre\DAVACL\Exception\NeedPrivileges;
-use \Sabre\HTTP\RequestInterface;
-use \Sabre\HTTP\ResponseInterface;
-use Sabre\HTTP\URLUtil;
-
-/**
- * Class DavAclPlugin is a wrapper around \Sabre\DAVACL\Plugin that returns 404
- * responses in case the resource to a response has been forbidden instead of
- * a 403. This is used to prevent enumeration of valid resources.
- *
- * @see https://github.com/owncloud/core/issues/22578
- * @package OCA\DAV\Connector\Sabre
- */
-class DavAclPlugin extends \Sabre\DAVACL\Plugin {
- public function __construct() {
- $this->hideNodesFromListings = true;
- }
-
- function checkPrivileges($uri, $privileges, $recursion = self::R_PARENT, $throwExceptions = true) {
- $access = parent::checkPrivileges($uri, $privileges, $recursion, false);
- if($access === false && $throwExceptions) {
- /** @var INode $node */
- $node = $this->server->tree->getNodeForPath($uri);
-
- switch(get_class($node)) {
- case 'OCA\DAV\CardDAV\AddressBook':
- $type = 'Addressbook';
- break;
- default:
- $type = 'Node';
- break;
- }
- throw new NotFound(
- sprintf(
- "%s with name '%s' could not be found",
- $type,
- $node->getName()
- )
- );
- }
-
- return $access;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/directory.php b/apps/dav/lib/connector/sabre/directory.php
deleted file mode 100644
index daa5f29ce79..00000000000
--- a/apps/dav/lib/connector/sabre/directory.php
+++ /dev/null
@@ -1,310 +0,0 @@
-<?php
-/**
- * @author Arthur Schiwon <blizzz@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <schiessle@owncloud.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre;
-
-use OCA\DAV\Connector\Sabre\Exception\Forbidden;
-use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
-use OCA\DAV\Connector\Sabre\Exception\FileLocked;
-use OCP\Files\ForbiddenException;
-use OCP\Lock\ILockingProvider;
-use OCP\Lock\LockedException;
-use Sabre\DAV\Exception\Locked;
-
-class Directory extends \OCA\DAV\Connector\Sabre\Node
- implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota {
-
- /**
- * Cached directory content
- *
- * @var \OCP\Files\FileInfo[]
- */
- private $dirContent;
-
- /**
- * Cached quota info
- *
- * @var array
- */
- private $quotaInfo;
-
- /**
- * @var ObjectTree|null
- */
- private $tree;
-
- /**
- * Sets up the node, expects a full path name
- *
- * @param \OC\Files\View $view
- * @param \OCP\Files\FileInfo $info
- * @param ObjectTree|null $tree
- * @param \OCP\Share\IManager $shareManager
- */
- public function __construct($view, $info, $tree = null, $shareManager = null) {
- parent::__construct($view, $info, $shareManager);
- $this->tree = $tree;
- }
-
- /**
- * Creates a new file in the directory
- *
- * Data will either be supplied as a stream resource, or in certain cases
- * as a string. Keep in mind that you may have to support either.
- *
- * After successful creation of the file, you may choose to return the ETag
- * of the new file here.
- *
- * The returned ETag must be surrounded by double-quotes (The quotes should
- * be part of the actual string).
- *
- * If you cannot accurately determine the ETag, you should not return it.
- * If you don't store the file exactly as-is (you're transforming it
- * somehow) you should also not return an ETag.
- *
- * This means that if a subsequent GET to this new file does not exactly
- * return the same contents of what was submitted here, you are strongly
- * recommended to omit the ETag.
- *
- * @param string $name Name of the file
- * @param resource|string $data Initial payload
- * @return null|string
- * @throws Exception\EntityTooLarge
- * @throws Exception\UnsupportedMediaType
- * @throws FileLocked
- * @throws InvalidPath
- * @throws \Sabre\DAV\Exception
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws \Sabre\DAV\Exception\Forbidden
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
- */
- public function createFile($name, $data = null) {
-
- try {
- // for chunked upload also updating a existing file is a "createFile"
- // because we create all the chunks before re-assemble them to the existing file.
- if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
-
- // exit if we can't create a new file and we don't updatable existing file
- $info = \OC_FileChunking::decodeName($name);
- if (!$this->fileView->isCreatable($this->path) &&
- !$this->fileView->isUpdatable($this->path . '/' . $info['name'])
- ) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
-
- } else {
- // For non-chunked upload it is enough to check if we can create a new file
- if (!$this->fileView->isCreatable($this->path)) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
- }
-
- $this->fileView->verifyPath($this->path, $name);
-
- $path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
- // using a dummy FileInfo is acceptable here since it will be refreshed after the put is complete
- $info = new \OC\Files\FileInfo($path, null, null, array(), null);
- $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
- $node->acquireLock(ILockingProvider::LOCK_SHARED);
- return $node->put($data);
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- } catch (ForbiddenException $ex) {
- throw new Forbidden($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- }
-
- /**
- * Creates a new subdirectory
- *
- * @param string $name
- * @throws FileLocked
- * @throws InvalidPath
- * @throws \Sabre\DAV\Exception\Forbidden
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
- */
- public function createDirectory($name) {
- try {
- if (!$this->info->isCreatable()) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
-
- $this->fileView->verifyPath($this->path, $name);
- $newPath = $this->path . '/' . $name;
- if (!$this->fileView->mkdir($newPath)) {
- throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
- }
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- } catch (ForbiddenException $ex) {
- throw new Forbidden($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- }
-
- /**
- * Returns a specific child node, referenced by its name
- *
- * @param string $name
- * @param \OCP\Files\FileInfo $info
- * @return \Sabre\DAV\INode
- * @throws InvalidPath
- * @throws \Sabre\DAV\Exception\NotFound
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
- */
- public function getChild($name, $info = null) {
- $path = $this->path . '/' . $name;
- if (is_null($info)) {
- try {
- $this->fileView->verifyPath($this->path, $name);
- $info = $this->fileView->getFileInfo($path);
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- }
- }
-
- if (!$info) {
- throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
- }
-
- if ($info['mimetype'] == 'httpd/unix-directory') {
- $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
- } else {
- $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info, $this->shareManager);
- }
- if ($this->tree) {
- $this->tree->cacheNode($node);
- }
- return $node;
- }
-
- /**
- * Returns an array with all the child nodes
- *
- * @return \Sabre\DAV\INode[]
- */
- public function getChildren() {
- if (!is_null($this->dirContent)) {
- return $this->dirContent;
- }
- try {
- $folderContent = $this->fileView->getDirectoryContent($this->path);
- } catch (LockedException $e) {
- throw new Locked();
- }
-
- $nodes = array();
- foreach ($folderContent as $info) {
- $node = $this->getChild($info->getName(), $info);
- $nodes[] = $node;
- }
- $this->dirContent = $nodes;
- return $this->dirContent;
- }
-
- /**
- * Checks if a child exists.
- *
- * @param string $name
- * @return bool
- */
- public function childExists($name) {
- // note: here we do NOT resolve the chunk file name to the real file name
- // to make sure we return false when checking for file existence with a chunk
- // file name.
- // This is to make sure that "createFile" is still triggered
- // (required old code) instead of "updateFile".
- //
- // TODO: resolve chunk file name here and implement "updateFile"
- $path = $this->path . '/' . $name;
- return $this->fileView->file_exists($path);
-
- }
-
- /**
- * Deletes all files in this directory, and then itself
- *
- * @return void
- * @throws FileLocked
- * @throws \Sabre\DAV\Exception\Forbidden
- */
- public function delete() {
-
- if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
-
- try {
- if (!$this->fileView->rmdir($this->path)) {
- // assume it wasn't possible to remove due to permission issue
- throw new \Sabre\DAV\Exception\Forbidden();
- }
- } catch (ForbiddenException $ex) {
- throw new Forbidden($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- }
-
- /**
- * Returns available diskspace information
- *
- * @return array
- */
- public function getQuotaInfo() {
- if ($this->quotaInfo) {
- return $this->quotaInfo;
- }
- try {
- $storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info);
- if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
- $free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
- } else {
- $free = $storageInfo['free'];
- }
- $this->quotaInfo = array(
- $storageInfo['used'],
- $free
- );
- return $this->quotaInfo;
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- return array(0, 0);
- }
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/dummygetresponseplugin.php b/apps/dav/lib/connector/sabre/dummygetresponseplugin.php
deleted file mode 100644
index b10d5aaab36..00000000000
--- a/apps/dav/lib/connector/sabre/dummygetresponseplugin.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-use Sabre\HTTP\ResponseInterface;
-use Sabre\HTTP\RequestInterface;
-
-/**
- * Class DummyGetResponsePlugin is a plugin used to not show a "Not implemented"
- * error to clients that rely on verifying the functionality of the ownCloud
- * WebDAV backend using a simple GET to /.
- *
- * This is considered a legacy behaviour and implementers should consider sending
- * a PROPFIND request instead to verify whether the WebDAV component is working
- * properly.
- *
- * FIXME: Remove once clients are all compliant.
- *
- * @package OCA\DAV\Connector\Sabre
- */
-class DummyGetResponsePlugin extends \Sabre\DAV\ServerPlugin {
- /** @var \Sabre\DAV\Server */
- protected $server;
-
- /**
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- function initialize(\Sabre\DAV\Server $server) {
- $this->server = $server;
- $this->server->on('method:GET', [$this, 'httpGet'], 200);
- }
-
- /**
- * @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 ownCloud desktop sync client.';
- $stream = fopen('php://memory','r+');
- fwrite($stream, $string);
- rewind($stream);
-
- $response->setStatus(200);
- $response->setBody($stream);
-
- return false;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/exception/entitytoolarge.php b/apps/dav/lib/connector/sabre/exception/entitytoolarge.php
deleted file mode 100644
index d16e93bb637..00000000000
--- a/apps/dav/lib/connector/sabre/exception/entitytoolarge.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre\Exception;
-
-/**
- * Entity Too Large
- *
- * This exception is thrown whenever a user tries to upload a file which exceeds hard limitations
- *
- */
-class EntityTooLarge extends \Sabre\DAV\Exception {
-
- /**
- * Returns the HTTP status code for this exception
- *
- * @return int
- */
- public function getHTTPCode() {
-
- return 413;
-
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/exception/filelocked.php b/apps/dav/lib/connector/sabre/exception/filelocked.php
deleted file mode 100644
index 03ced0e81e2..00000000000
--- a/apps/dav/lib/connector/sabre/exception/filelocked.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Owen Winkler <a_github@midnightcircus.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre\Exception;
-
-use Exception;
-
-class FileLocked extends \Sabre\DAV\Exception {
-
- public function __construct($message = "", $code = 0, Exception $previous = null) {
- if($previous instanceof \OCP\Files\LockNotAcquiredException) {
- $message = sprintf('Target file %s is locked by another process.', $previous->path);
- }
- parent::__construct($message, $code, $previous);
- }
-
- /**
- * Returns the HTTP status code for this exception
- *
- * @return int
- */
- public function getHTTPCode() {
-
- return 423;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/exception/forbidden.php b/apps/dav/lib/connector/sabre/exception/forbidden.php
deleted file mode 100644
index f2467e6b298..00000000000
--- a/apps/dav/lib/connector/sabre/exception/forbidden.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre\Exception;
-
-class Forbidden extends \Sabre\DAV\Exception\Forbidden {
-
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
-
- /**
- * @var bool
- */
- private $retry;
-
- /**
- * @param string $message
- * @param bool $retry
- * @param \Exception $previous
- */
- public function __construct($message, $retry = false, \Exception $previous = null) {
- parent::__construct($message, 0, $previous);
- $this->retry = $retry;
- }
-
- /**
- * This method allows the exception to include additional information
- * into the WebDAV error response
- *
- * @param \Sabre\DAV\Server $server
- * @param \DOMElement $errorNode
- * @return void
- */
- public function serialize(\Sabre\DAV\Server $server,\DOMElement $errorNode) {
-
- // set ownCloud namespace
- $errorNode->setAttribute('xmlns:o', self::NS_OWNCLOUD);
-
- // adding the retry node
- $error = $errorNode->ownerDocument->createElementNS('o:','o:retry', var_export($this->retry, true));
- $errorNode->appendChild($error);
-
- // adding the message node
- $error = $errorNode->ownerDocument->createElementNS('o:','o:reason', $this->getMessage());
- $errorNode->appendChild($error);
- }
-}
diff --git a/apps/dav/lib/connector/sabre/exception/invalidpath.php b/apps/dav/lib/connector/sabre/exception/invalidpath.php
deleted file mode 100644
index 7951a0a89b7..00000000000
--- a/apps/dav/lib/connector/sabre/exception/invalidpath.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre\Exception;
-
-use Sabre\DAV\Exception;
-
-class InvalidPath extends Exception {
-
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
-
- /**
- * @var bool
- */
- private $retry;
-
- /**
- * @param string $message
- * @param bool $retry
- */
- public function __construct($message, $retry = false) {
- parent::__construct($message);
- $this->retry = $retry;
- }
-
- /**
- * Returns the HTTP status code for this exception
- *
- * @return int
- */
- public function getHTTPCode() {
-
- return 400;
-
- }
-
- /**
- * This method allows the exception to include additional information
- * into the WebDAV error response
- *
- * @param \Sabre\DAV\Server $server
- * @param \DOMElement $errorNode
- * @return void
- */
- public function serialize(\Sabre\DAV\Server $server,\DOMElement $errorNode) {
-
- // set ownCloud namespace
- $errorNode->setAttribute('xmlns:o', self::NS_OWNCLOUD);
-
- // adding the retry node
- $error = $errorNode->ownerDocument->createElementNS('o:','o:retry', var_export($this->retry, true));
- $errorNode->appendChild($error);
-
- // adding the message node
- $error = $errorNode->ownerDocument->createElementNS('o:','o:reason', $this->getMessage());
- $errorNode->appendChild($error);
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/exception/unsupportedmediatype.php b/apps/dav/lib/connector/sabre/exception/unsupportedmediatype.php
deleted file mode 100644
index 99e3c222c75..00000000000
--- a/apps/dav/lib/connector/sabre/exception/unsupportedmediatype.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre\Exception;
-
-/**
- * Unsupported Media Type
- *
- * This exception is thrown whenever a user tries to upload a file which holds content which is not allowed
- *
- */
-class UnsupportedMediaType extends \Sabre\DAV\Exception {
-
- /**
- * Returns the HTTP status code for this exception
- *
- * @return int
- */
- public function getHTTPCode() {
-
- return 415;
-
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/exceptionloggerplugin.php b/apps/dav/lib/connector/sabre/exceptionloggerplugin.php
deleted file mode 100644
index 38bddef8769..00000000000
--- a/apps/dav/lib/connector/sabre/exceptionloggerplugin.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Pierre Jochem <pierrejochem@msn.com>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\ILogger;
-use Sabre\DAV\Exception;
-use Sabre\HTTP\Response;
-
-class ExceptionLoggerPlugin extends \Sabre\DAV\ServerPlugin {
- protected $nonFatalExceptions = array(
- 'Sabre\DAV\Exception\NotAuthenticated' => true,
- // the sync client uses this to find out whether files exist,
- // so it is not always an error, log it as debug
- 'Sabre\DAV\Exception\NotFound' => true,
- // this one mostly happens when the same file is uploaded at
- // exactly the same time from two clients, only one client
- // wins, the second one gets "Precondition failed"
- 'Sabre\DAV\Exception\PreconditionFailed' => true,
- // forbidden can be expected when trying to upload to
- // read-only folders for example
- 'Sabre\DAV\Exception\Forbidden' => true,
- );
-
- /** @var string */
- private $appName;
-
- /** @var ILogger */
- private $logger;
-
- /**
- * @param string $loggerAppName app name to use when logging
- * @param ILogger $logger
- */
- public function __construct($loggerAppName, $logger) {
- $this->appName = $loggerAppName;
- $this->logger = $logger;
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
-
- $server->on('exception', array($this, 'logException'), 10);
- }
-
- /**
- * Log exception
- *
- */
- public function logException(\Exception $ex) {
- $exceptionClass = get_class($ex);
- $level = \OCP\Util::FATAL;
- if (isset($this->nonFatalExceptions[$exceptionClass])) {
- $level = \OCP\Util::DEBUG;
- }
-
- $message = $ex->getMessage();
- if ($ex instanceof Exception) {
- if (empty($message)) {
- $response = new Response($ex->getHTTPCode());
- $message = $response->getStatusText();
- }
- $message = "HTTP/1.1 {$ex->getHTTPCode()} $message";
- }
-
- $user = \OC_User::getUser();
-
- $exception = [
- 'Message' => $message,
- 'Exception' => $exceptionClass,
- 'Code' => $ex->getCode(),
- 'Trace' => $ex->getTraceAsString(),
- 'File' => $ex->getFile(),
- 'Line' => $ex->getLine(),
- 'User' => $user,
- ];
- $this->logger->log($level, 'Exception: ' . json_encode($exception), ['app' => $this->appName]);
- }
-}
diff --git a/apps/dav/lib/connector/sabre/fakelockerplugin.php b/apps/dav/lib/connector/sabre/fakelockerplugin.php
deleted file mode 100644
index 6db8740bc13..00000000000
--- a/apps/dav/lib/connector/sabre/fakelockerplugin.php
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use Sabre\DAV\Locks\LockInfo;
-use Sabre\DAV\ServerPlugin;
-use Sabre\DAV\Xml\Property\LockDiscovery;
-use Sabre\DAV\Xml\Property\SupportedLock;
-use Sabre\HTTP\RequestInterface;
-use Sabre\HTTP\ResponseInterface;
-use Sabre\DAV\PropFind;
-use Sabre\DAV\INode;
-
-/**
- * Class FakeLockerPlugin is a plugin only used when connections come in from
- * OS X via Finder. The fake locking plugin does emulate Class 2 WebDAV support
- * (locking of files) which allows Finder to access the storage in write mode as
- * well.
- *
- * No real locking is performed, instead the plugin just returns always positive
- * responses.
- *
- * @see https://github.com/owncloud/core/issues/17732
- * @package OCA\DAV\Connector\Sabre
- */
-class FakeLockerPlugin extends ServerPlugin {
- /** @var \Sabre\DAV\Server */
- private $server;
-
- /** {@inheritDoc} */
- public function initialize(\Sabre\DAV\Server $server) {
- $this->server = $server;
- $this->server->on('method:LOCK', [$this, 'fakeLockProvider'], 1);
- $this->server->on('method:UNLOCK', [$this, 'fakeUnlockProvider'], 1);
- $server->on('propFind', [$this, 'propFind']);
- $server->on('validateTokens', [$this, 'validateTokens']);
- }
-
- /**
- * Indicate that we support LOCK and UNLOCK
- *
- * @param string $path
- * @return string[]
- */
- public function getHTTPMethods($path) {
- return [
- 'LOCK',
- 'UNLOCK',
- ];
- }
-
- /**
- * Indicate that we support locking
- *
- * @return integer[]
- */
- function getFeatures() {
- return [2];
- }
-
- /**
- * Return some dummy response for PROPFIND requests with regard to locking
- *
- * @param PropFind $propFind
- * @param INode $node
- * @return void
- */
- function propFind(PropFind $propFind, INode $node) {
- $propFind->handle('{DAV:}supportedlock', function() {
- return new SupportedLock(true);
- });
- $propFind->handle('{DAV:}lockdiscovery', function() use ($propFind) {
- return new LockDiscovery([]);
- });
- }
-
- /**
- * Mark a locking token always as valid
- *
- * @param RequestInterface $request
- * @param array $conditions
- */
- public function validateTokens(RequestInterface $request, &$conditions) {
- foreach($conditions as &$fileCondition) {
- if(isset($fileCondition['tokens'])) {
- foreach($fileCondition['tokens'] as &$token) {
- if(isset($token['token'])) {
- if(substr($token['token'], 0, 16) === 'opaquelocktoken:') {
- $token['validToken'] = true;
- }
- }
- }
- }
- }
- }
-
- /**
- * 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;
- }
-
- /**
- * Fakes a successful LOCK
- *
- * @param RequestInterface $request
- * @param ResponseInterface $response
- * @return bool
- */
- public function fakeUnlockProvider(RequestInterface $request,
- ResponseInterface $response) {
- $response->setStatus(204);
- $response->setHeader('Content-Length', '0');
- return false;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/file.php b/apps/dav/lib/connector/sabre/file.php
deleted file mode 100644
index 943e9150e74..00000000000
--- a/apps/dav/lib/connector/sabre/file.php
+++ /dev/null
@@ -1,567 +0,0 @@
-<?php
-/**
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <schiessle@owncloud.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Owen Winkler <a_github@midnightcircus.com>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OC\Files\Filesystem;
-use OCA\DAV\Connector\Sabre\Exception\EntityTooLarge;
-use OCA\DAV\Connector\Sabre\Exception\FileLocked;
-use OCA\DAV\Connector\Sabre\Exception\Forbidden as DAVForbiddenException;
-use OCA\DAV\Connector\Sabre\Exception\UnsupportedMediaType;
-use OCP\Encryption\Exceptions\GenericEncryptionException;
-use OCP\Files\EntityTooLargeException;
-use OCP\Files\ForbiddenException;
-use OCP\Files\InvalidContentException;
-use OCP\Files\InvalidPathException;
-use OCP\Files\LockNotAcquiredException;
-use OCP\Files\NotPermittedException;
-use OCP\Files\StorageNotAvailableException;
-use OCP\Lock\ILockingProvider;
-use OCP\Lock\LockedException;
-use Sabre\DAV\Exception;
-use Sabre\DAV\Exception\BadRequest;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\Exception\NotImplemented;
-use Sabre\DAV\Exception\ServiceUnavailable;
-use Sabre\DAV\IFile;
-
-class File extends Node implements IFile {
-
- /**
- * Updates the data
- *
- * The data argument is a readable stream resource.
- *
- * After a successful put operation, you may choose to return an ETag. The
- * etag must always be surrounded by double-quotes. These quotes must
- * appear in the actual string you're returning.
- *
- * Clients may use the ETag from a PUT request to later on make sure that
- * when they update the file, the contents haven't changed in the mean
- * time.
- *
- * If you don't plan to store the file byte-by-byte, and you return a
- * different object on a subsequent GET you are strongly recommended to not
- * return an ETag, and just return null.
- *
- * @param resource $data
- *
- * @throws Forbidden
- * @throws UnsupportedMediaType
- * @throws BadRequest
- * @throws Exception
- * @throws EntityTooLarge
- * @throws ServiceUnavailable
- * @throws FileLocked
- * @return string|null
- */
- public function put($data) {
- try {
- $exists = $this->fileView->file_exists($this->path);
- if ($this->info && $exists && !$this->info->isUpdateable()) {
- throw new Forbidden();
- }
- } catch (StorageNotAvailableException $e) {
- throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
- }
-
- // verify path of the target
- $this->verifyPath();
-
- // chunked handling
- if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
- try {
- return $this->createFileChunked($data);
- } catch (\Exception $e) {
- $this->convertToSabreException($e);
- }
- }
-
- list($partStorage) = $this->fileView->resolvePath($this->path);
- $needsPartFile = $this->needsPartFile($partStorage) && (strlen($this->path) > 1);
-
- if ($needsPartFile) {
- // mark file as partial while uploading (ignored by the scanner)
- $partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
- } else {
- // upload file directly as the final path
- $partFilePath = $this->path;
- }
-
- // the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
- /** @var \OC\Files\Storage\Storage $partStorage */
- list($partStorage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
- /** @var \OC\Files\Storage\Storage $storage */
- list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
- try {
- $target = $partStorage->fopen($internalPartPath, 'wb');
- if ($target === false) {
- \OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::fopen() failed', \OCP\Util::ERROR);
- // because we have no clue about the cause we can only throw back a 500/Internal Server Error
- throw new Exception('Could not write file contents');
- }
- list($count, $result) = \OC_Helper::streamCopy($data, $target);
- fclose($target);
-
- if ($result === false) {
- $expected = -1;
- if (isset($_SERVER['CONTENT_LENGTH'])) {
- $expected = $_SERVER['CONTENT_LENGTH'];
- }
- throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
- }
-
- // if content length is sent by client:
- // double check if the file was fully received
- // compare expected and actual size
- if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
- $expected = $_SERVER['CONTENT_LENGTH'];
- if ($count != $expected) {
- throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
- }
- }
-
- } catch (\Exception $e) {
- if ($needsPartFile) {
- $partStorage->unlink($internalPartPath);
- }
- $this->convertToSabreException($e);
- }
-
- try {
- $view = \OC\Files\Filesystem::getView();
- if ($view) {
- $run = $this->emitPreHooks($exists);
- } else {
- $run = true;
- }
-
- try {
- $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
- } catch (LockedException $e) {
- if ($needsPartFile) {
- $partStorage->unlink($internalPartPath);
- }
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
-
- if ($needsPartFile) {
- // rename to correct path
- try {
- if ($run) {
- $renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
- $fileExists = $storage->file_exists($internalPath);
- }
- if (!$run || $renameOkay === false || $fileExists === false) {
- \OCP\Util::writeLog('webdav', 'renaming part file to final file failed', \OCP\Util::ERROR);
- throw new Exception('Could not rename part file to final file');
- }
- } catch (ForbiddenException $ex) {
- throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
- } catch (\Exception $e) {
- $partStorage->unlink($internalPartPath);
- $this->convertToSabreException($e);
- }
- }
-
- // since we skipped the view we need to scan and emit the hooks ourselves
- $storage->getUpdater()->update($internalPath);
-
- try {
- $this->changeLock(ILockingProvider::LOCK_SHARED);
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
-
- if ($view) {
- $this->emitPostHooks($exists);
- }
-
- // allow sync clients to send the mtime along in a header
- $request = \OC::$server->getRequest();
- if (isset($request->server['HTTP_X_OC_MTIME'])) {
- if ($this->fileView->touch($this->path, $request->server['HTTP_X_OC_MTIME'])) {
- header('X-OC-MTime: accepted');
- }
- }
-
- $this->refreshInfo();
-
- if (isset($request->server['HTTP_OC_CHECKSUM'])) {
- $checksum = trim($request->server['HTTP_OC_CHECKSUM']);
- $this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
- $this->refreshInfo();
- } else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
- $this->fileView->putFileInfo($this->path, ['checksum' => '']);
- $this->refreshInfo();
- }
-
- } catch (StorageNotAvailableException $e) {
- throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
- }
-
- return '"' . $this->info->getEtag() . '"';
- }
-
- private function getPartFileBasePath($path) {
- $partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
- if ($partFileInStorage) {
- return $path;
- } else {
- return md5($path); // will place it in the root of the view with a unique name
- }
- }
-
- /**
- * @param string $path
- */
- private function emitPreHooks($exists, $path = null) {
- if (is_null($path)) {
- $path = $this->path;
- }
- $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
- $run = true;
-
- if (!$exists) {
- \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, array(
- \OC\Files\Filesystem::signal_param_path => $hookPath,
- \OC\Files\Filesystem::signal_param_run => &$run,
- ));
- } else {
- \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, array(
- \OC\Files\Filesystem::signal_param_path => $hookPath,
- \OC\Files\Filesystem::signal_param_run => &$run,
- ));
- }
- \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, array(
- \OC\Files\Filesystem::signal_param_path => $hookPath,
- \OC\Files\Filesystem::signal_param_run => &$run,
- ));
- return $run;
- }
-
- /**
- * @param string $path
- */
- private function emitPostHooks($exists, $path = null) {
- if (is_null($path)) {
- $path = $this->path;
- }
- $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
- if (!$exists) {
- \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, array(
- \OC\Files\Filesystem::signal_param_path => $hookPath
- ));
- } else {
- \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, array(
- \OC\Files\Filesystem::signal_param_path => $hookPath
- ));
- }
- \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, array(
- \OC\Files\Filesystem::signal_param_path => $hookPath
- ));
- }
-
- /**
- * Returns the data
- *
- * @return resource
- * @throws Forbidden
- * @throws ServiceUnavailable
- */
- public function get() {
- //throw exception if encryption is disabled but files are still encrypted
- try {
- $res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
- if ($res === false) {
- throw new ServiceUnavailable("Could not open file");
- }
- return $res;
- } catch (GenericEncryptionException $e) {
- // returning 503 will allow retry of the operation at a later point in time
- throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
- } catch (StorageNotAvailableException $e) {
- throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
- } catch (ForbiddenException $ex) {
- throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- }
-
- /**
- * Delete the current file
- *
- * @throws Forbidden
- * @throws ServiceUnavailable
- */
- public function delete() {
- if (!$this->info->isDeletable()) {
- throw new Forbidden();
- }
-
- try {
- if (!$this->fileView->unlink($this->path)) {
- // assume it wasn't possible to delete due to permissions
- throw new Forbidden();
- }
- } catch (StorageNotAvailableException $e) {
- throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
- } catch (ForbiddenException $ex) {
- throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- }
-
- /**
- * Returns the mime-type for a file
- *
- * If null is returned, we'll assume application/octet-stream
- *
- * @return string
- */
- public function getContentType() {
- $mimeType = $this->info->getMimetype();
-
- // PROPFIND needs to return the correct mime type, for consistency with the web UI
- if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
- return $mimeType;
- }
- return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
- }
-
- /**
- * @return array|false
- */
- public function getDirectDownload() {
- if (\OCP\App::isEnabled('encryption')) {
- return [];
- }
- /** @var \OCP\Files\Storage $storage */
- list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
- if (is_null($storage)) {
- return [];
- }
-
- return $storage->getDirectDownload($internalPath);
- }
-
- /**
- * @param resource $data
- * @return null|string
- * @throws Exception
- * @throws BadRequest
- * @throws NotImplemented
- * @throws ServiceUnavailable
- */
- private function createFileChunked($data) {
- list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);
-
- $info = \OC_FileChunking::decodeName($name);
- if (empty($info)) {
- throw new NotImplemented('Invalid chunk name');
- }
-
- $chunk_handler = new \OC_FileChunking($info);
- $bytesWritten = $chunk_handler->store($info['index'], $data);
-
- //detect aborted upload
- if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
- if (isset($_SERVER['CONTENT_LENGTH'])) {
- $expected = $_SERVER['CONTENT_LENGTH'];
- if ($bytesWritten != $expected) {
- $chunk_handler->remove($info['index']);
- throw new BadRequest(
- 'expected filesize ' . $expected . ' got ' . $bytesWritten);
- }
- }
- }
-
- if ($chunk_handler->isComplete()) {
- list($storage,) = $this->fileView->resolvePath($path);
- $needsPartFile = $this->needsPartFile($storage);
- $partFile = null;
-
- $targetPath = $path . '/' . $info['name'];
- /** @var \OC\Files\Storage\Storage $targetStorage */
- list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
-
- $exists = $this->fileView->file_exists($targetPath);
-
- try {
- $this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
-
- $this->emitPreHooks($exists, $targetPath);
- $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
- /** @var \OC\Files\Storage\Storage $targetStorage */
- list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
-
- if ($needsPartFile) {
- // we first assembly the target file as a part file
- $partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
- /** @var \OC\Files\Storage\Storage $targetStorage */
- list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
-
-
- $chunk_handler->file_assemble($partStorage, $partInternalPath);
-
- // here is the final atomic rename
- $renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
- $fileExists = $targetStorage->file_exists($targetInternalPath);
- if ($renameOkay === false || $fileExists === false) {
- \OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::rename() failed', \OCP\Util::ERROR);
- // only delete if an error occurred and the target file was already created
- if ($fileExists) {
- // set to null to avoid double-deletion when handling exception
- // stray part file
- $partFile = null;
- $targetStorage->unlink($targetInternalPath);
- }
- $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
- throw new Exception('Could not rename part file assembled from chunks');
- }
- } else {
- // assemble directly into the final file
- $chunk_handler->file_assemble($targetStorage, $targetInternalPath);
- }
-
- // allow sync clients to send the mtime along in a header
- $request = \OC::$server->getRequest();
- if (isset($request->server['HTTP_X_OC_MTIME'])) {
- if ($targetStorage->touch($targetInternalPath, $request->server['HTTP_X_OC_MTIME'])) {
- header('X-OC-MTime: accepted');
- }
- }
-
- // since we skipped the view we need to scan and emit the hooks ourselves
- $targetStorage->getUpdater()->update($targetInternalPath);
-
- $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
-
- $this->emitPostHooks($exists, $targetPath);
-
- // FIXME: should call refreshInfo but can't because $this->path is not the of the final file
- $info = $this->fileView->getFileInfo($targetPath);
-
- if (isset($request->server['HTTP_OC_CHECKSUM'])) {
- $checksum = trim($request->server['HTTP_OC_CHECKSUM']);
- $this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
- } else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
- $this->fileView->putFileInfo($this->path, ['checksum' => '']);
- }
-
- $this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
-
- return $info->getEtag();
- } catch (\Exception $e) {
- if ($partFile !== null) {
- $targetStorage->unlink($targetInternalPath);
- }
- $this->convertToSabreException($e);
- }
- }
-
- return null;
- }
-
- /**
- * Returns whether a part file is needed for the given storage
- * or whether the file can be assembled/uploaded directly on the
- * target storage.
- *
- * @param \OCP\Files\Storage $storage
- * @return bool true if the storage needs part file handling
- */
- private function needsPartFile($storage) {
- // TODO: in the future use ChunkHandler provided by storage
- // and/or add method on Storage called "needsPartFile()"
- return !$storage->instanceOfStorage('OCA\Files_Sharing\External\Storage') &&
- !$storage->instanceOfStorage('OC\Files\Storage\OwnCloud');
- }
-
- /**
- * Convert the given exception to a SabreException instance
- *
- * @param \Exception $e
- *
- * @throws \Sabre\DAV\Exception
- */
- private function convertToSabreException(\Exception $e) {
- if ($e instanceof \Sabre\DAV\Exception) {
- throw $e;
- }
- if ($e instanceof NotPermittedException) {
- // a more general case - due to whatever reason the content could not be written
- throw new Forbidden($e->getMessage(), 0, $e);
- }
- if ($e instanceof ForbiddenException) {
- // the path for the file was forbidden
- throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
- }
- if ($e instanceof EntityTooLargeException) {
- // the file is too big to be stored
- throw new EntityTooLarge($e->getMessage(), 0, $e);
- }
- if ($e instanceof InvalidContentException) {
- // the file content is not permitted
- throw new UnsupportedMediaType($e->getMessage(), 0, $e);
- }
- if ($e instanceof InvalidPathException) {
- // the path for the file was not valid
- // TODO: find proper http status code for this case
- throw new Forbidden($e->getMessage(), 0, $e);
- }
- if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
- // the file is currently being written to by another process
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- if ($e instanceof GenericEncryptionException) {
- // returning 503 will allow retry of the operation at a later point in time
- throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
- }
- if ($e instanceof StorageNotAvailableException) {
- throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
- }
-
- throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
- }
-
- /**
- * Get the checksum for this file
- *
- * @return string
- */
- public function getChecksum() {
- return $this->info->getChecksum();
- }
-}
diff --git a/apps/dav/lib/connector/sabre/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php
deleted file mode 100644
index 8822deb1661..00000000000
--- a/apps/dav/lib/connector/sabre/filesplugin.php
+++ /dev/null
@@ -1,398 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OC\Files\View;
-use OCA\DAV\Upload\FutureFile;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\IFile;
-use \Sabre\DAV\PropFind;
-use \Sabre\DAV\PropPatch;
-use Sabre\DAV\ServerPlugin;
-use Sabre\DAV\Tree;
-use \Sabre\HTTP\RequestInterface;
-use \Sabre\HTTP\ResponseInterface;
-use OCP\Files\StorageNotAvailableException;
-use OCP\IConfig;
-
-class FilesPlugin extends ServerPlugin {
-
- // namespace
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
- const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
- const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
- const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
- const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
- const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
- const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
- const GETETAG_PROPERTYNAME = '{DAV:}getetag';
- const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
- const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
- const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
- const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
- const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
-
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var Tree
- */
- private $tree;
-
- /**
- * Whether this is public webdav.
- * If true, some returned information will be stripped off.
- *
- * @var bool
- */
- private $isPublic;
-
- /**
- * @var View
- */
- private $fileView;
-
- /**
- * @var bool
- */
- private $downloadAttachment;
-
- /**
- * @var IConfig
- */
- private $config;
-
- /**
- * @param Tree $tree
- * @param View $view
- * @param bool $isPublic
- * @param bool $downloadAttachment
- */
- public function __construct(Tree $tree,
- View $view,
- IConfig $config,
- $isPublic = false,
- $downloadAttachment = true) {
- $this->tree = $tree;
- $this->fileView = $view;
- $this->config = $config;
- $this->isPublic = $isPublic;
- $this->downloadAttachment = $downloadAttachment;
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
-
- $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
- $server->protectedProperties[] = self::FILEID_PROPERTYNAME;
- $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
- $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
- $server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
- $server->protectedProperties[] = self::SIZE_PROPERTYNAME;
- $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
- $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
- $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
- $server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
- $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
-
- // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
- $allowedProperties = ['{DAV:}getetag'];
- $server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
-
- $this->server = $server;
- $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('afterMethod:GET', [$this,'httpGet']);
- $this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
- $this->server->on('afterResponse', function($request, ResponseInterface $response) {
- $body = $response->getBody();
- if (is_resource($body)) {
- fclose($body);
- }
- });
- $this->server->on('beforeMove', [$this, 'checkMove']);
- }
-
- /**
- * Plugin that checks if a move can actually be performed.
- *
- * @param string $source source path
- * @param string $destination destination path
- * @throws Forbidden
- * @throws NotFound
- */
- function checkMove($source, $destination) {
- $sourceNode = $this->tree->getNodeForPath($source);
- if ($sourceNode instanceof FutureFile) {
- return;
- }
- list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
- list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
-
- if ($sourceDir !== $destinationDir) {
- $sourceFileInfo = $this->fileView->getFileInfo($source);
-
- if ($sourceFileInfo === false) {
- throw new NotFound($source . ' does not exist');
- }
-
- if (!$sourceFileInfo->isDeletable()) {
- throw new Forbidden($source . " cannot be deleted");
- }
- }
- }
-
- /**
- * This sets a cookie to be able to recognize the start of the download
- * the content must not be longer than 32 characters and must only contain
- * alphanumeric characters
- *
- * @param RequestInterface $request
- * @param ResponseInterface $response
- */
- function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
- $queryParams = $request->getQueryParameters();
-
- /**
- * this sets a cookie to be able to recognize the start of the download
- * the content must not be longer than 32 characters and must only contain
- * alphanumeric characters
- */
- if (isset($queryParams['downloadStartSecret'])) {
- $token = $queryParams['downloadStartSecret'];
- if (!isset($token[32])
- && preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
- // FIXME: use $response->setHeader() instead
- setcookie('ocDownloadStarted', $token, time() + 20, '/');
- }
- }
- }
-
- /**
- * Add headers to file download
- *
- * @param RequestInterface $request
- * @param ResponseInterface $response
- */
- function httpGet(RequestInterface $request, ResponseInterface $response) {
- // Only handle valid files
- $node = $this->tree->getNodeForPath($request->getPath());
- if (!($node instanceof IFile)) return;
-
- // adds a 'Content-Disposition: attachment' header
- if ($this->downloadAttachment) {
- $response->addHeader('Content-Disposition', 'attachment');
- }
-
- if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
- //Add OC-Checksum header
- /** @var $node File */
- $checksum = $node->getChecksum();
- if ($checksum !== null && $checksum !== '') {
- $response->addHeader('OC-Checksum', $checksum);
- }
- }
- }
-
- /**
- * Adds all ownCloud-specific properties
- *
- * @param PropFind $propFind
- * @param \Sabre\DAV\INode $node
- * @return void
- */
- public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
-
- $httpRequest = $this->server->httpRequest;
-
- if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
-
- $propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
- return $node->getFileId();
- });
-
- $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
- return $node->getInternalFileId();
- });
-
- $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
- $perms = $node->getDavPermissions();
- if ($this->isPublic) {
- // remove mount information
- $perms = str_replace(['S', 'M'], '', $perms);
- }
- return $perms;
- });
-
- $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
- return $node->getSharePermissions(
- $httpRequest->getRawServerValue('PHP_AUTH_USER')
- );
- });
-
- $propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
- return $node->getETag();
- });
-
- $propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
- $owner = $node->getOwner();
- return $owner->getUID();
- });
- $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
- $owner = $node->getOwner();
- $displayName = $owner->getDisplayName();
- return $displayName;
- });
-
- $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
- if ($node->getPath() === '/') {
- return $this->config->getSystemValue('data-fingerprint', '');
- }
- });
- }
-
- if ($node instanceof \OCA\DAV\Files\FilesHome) {
- $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
- return $this->config->getSystemValue('data-fingerprint', '');
- });
- }
-
- if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
- $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
- /** @var $node \OCA\DAV\Connector\Sabre\File */
- try {
- $directDownloadUrl = $node->getDirectDownload();
- if (isset($directDownloadUrl['url'])) {
- return $directDownloadUrl['url'];
- }
- } catch (StorageNotAvailableException $e) {
- return false;
- }
- return false;
- });
-
- $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
- $checksum = $node->getChecksum();
- if ($checksum === NULL || $checksum === '') {
- return null;
- }
-
- return new ChecksumList($checksum);
- });
-
- }
-
- if ($node instanceof \OCA\DAV\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::LASTMODIFIED_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
- */
- public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
- // chunked upload handling
- if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
- list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
- $info = \OC_FileChunking::decodeName($name);
- if (!empty($info)) {
- $filePath = $path . '/' . $info['name'];
- }
- }
-
- // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
- if (!$this->server->tree->nodeExists($filePath)) {
- return;
- }
- $node = $this->server->tree->getNodeForPath($filePath);
- if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
- $fileId = $node->getFileId();
- if (!is_null($fileId)) {
- $this->server->httpResponse->setHeader('OC-FileId', $fileId);
- }
- }
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/filesreportplugin.php b/apps/dav/lib/connector/sabre/filesreportplugin.php
deleted file mode 100644
index d4e1cbe3b20..00000000000
--- a/apps/dav/lib/connector/sabre/filesreportplugin.php
+++ /dev/null
@@ -1,333 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OC\Files\View;
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\Exception\PreconditionFailed;
-use Sabre\DAV\Exception\ReportNotSupported;
-use Sabre\DAV\Exception\BadRequest;
-use Sabre\DAV\ServerPlugin;
-use Sabre\DAV\Tree;
-use Sabre\DAV\Xml\Element\Response;
-use Sabre\DAV\Xml\Response\MultiStatus;
-use Sabre\DAV\PropFind;
-use OCP\SystemTag\ISystemTagObjectMapper;
-use OCP\IUserSession;
-use OCP\Files\Folder;
-use OCP\IGroupManager;
-use OCP\SystemTag\ISystemTagManager;
-use OCP\SystemTag\TagNotFoundException;
-
-class FilesReportPlugin extends ServerPlugin {
-
- // namespace
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
- const REPORT_NAME = '{http://owncloud.org/ns}filter-files';
- const SYSTEMTAG_PROPERTYNAME = '{http://owncloud.org/ns}systemtag';
-
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var Tree
- */
- private $tree;
-
- /**
- * @var View
- */
- private $fileView;
-
- /**
- * @var ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var ISystemTagObjectMapper
- */
- private $tagMapper;
-
- /**
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * @var IGroupManager
- */
- private $groupManager;
-
- /**
- * @var Folder
- */
- private $userFolder;
-
- /**
- * @param Tree $tree
- * @param View $view
- */
- public function __construct(Tree $tree,
- View $view,
- ISystemTagManager $tagManager,
- ISystemTagObjectMapper $tagMapper,
- IUserSession $userSession,
- IGroupManager $groupManager,
- Folder $userFolder
- ) {
- $this->tree = $tree;
- $this->fileView = $view;
- $this->tagManager = $tagManager;
- $this->tagMapper = $tagMapper;
- $this->userSession = $userSession;
- $this->groupManager = $groupManager;
- $this->userFolder = $userFolder;
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
-
- $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
-
- $this->server = $server;
- $this->server->on('report', array($this, 'onReport'));
- }
-
- /**
- * Returns a list of reports this plugin supports.
- *
- * This will be used in the {DAV:}supported-report-set property.
- *
- * @param string $uri
- * @return array
- */
- public function getSupportedReportSet($uri) {
- return [self::REPORT_NAME];
- }
-
- /**
- * REPORT operations to look for files
- *
- * @param string $reportName
- * @param [] $report
- * @param string $uri
- * @return bool
- * @throws NotFound
- * @throws ReportNotSupported
- */
- public function onReport($reportName, $report, $uri) {
- $reportTargetNode = $this->server->tree->getNodeForPath($uri);
- if (!$reportTargetNode instanceof Directory || $reportName !== self::REPORT_NAME) {
- throw new ReportNotSupported();
- }
-
- $ns = '{' . $this::NS_OWNCLOUD . '}';
- $requestedProps = [];
- $filterRules = [];
-
- // parse report properties and gather filter info
- foreach ($report as $reportProps) {
- $name = $reportProps['name'];
- if ($name === $ns . 'filter-rules') {
- $filterRules = $reportProps['value'];
- } else if ($name === '{DAV:}prop') {
- // propfind properties
- foreach ($reportProps['value'] as $propVal) {
- $requestedProps[] = $propVal['name'];
- }
- }
- }
-
- if (empty($filterRules)) {
- // an empty filter would return all existing files which would be slow
- throw new BadRequest('Missing filter-rule block in request');
- }
-
- // gather all file ids matching filter
- try {
- $resultFileIds = $this->processFilterRules($filterRules);
- } catch (TagNotFoundException $e) {
- throw new PreconditionFailed('Cannot filter by non-existing tag', 0, $e);
- }
-
- // find sabre nodes by file id, restricted to the root node path
- $results = $this->findNodesByFileIds($reportTargetNode, $resultFileIds);
-
- $responses = $this->prepareResponses($requestedProps, $results);
-
- $xml = $this->server->xml->write(
- '{DAV:}multistatus',
- new MultiStatus($responses)
- );
-
- $this->server->httpResponse->setStatus(207);
- $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
- $this->server->httpResponse->setBody($xml);
-
- return false;
- }
-
- /**
- * Find file ids matching the given filter rules
- *
- * @param array $filterRules
- * @return array array of unique file id results
- *
- * @throws TagNotFoundException whenever a tag was not found
- */
- protected function processFilterRules($filterRules) {
- $ns = '{' . $this::NS_OWNCLOUD . '}';
- $resultFileIds = null;
- $systemTagIds = [];
- foreach ($filterRules as $filterRule) {
- if ($filterRule['name'] === $ns . 'systemtag') {
- $systemTagIds[] = $filterRule['value'];
- }
- }
-
- // check user permissions, if applicable
- if (!$this->isAdmin()) {
- // check visibility/permission
- $tags = $this->tagManager->getTagsByIds($systemTagIds);
- $unknownTagIds = [];
- foreach ($tags as $tag) {
- if (!$tag->isUserVisible()) {
- $unknownTagIds[] = $tag->getId();
- }
- }
-
- if (!empty($unknownTagIds)) {
- throw new TagNotFoundException('Tag with ids ' . implode(', ', $unknownTagIds) . ' not found');
- }
- }
-
- // fetch all file ids and intersect them
- foreach ($systemTagIds as $systemTagId) {
- $fileIds = $this->tagMapper->getObjectIdsForTags($systemTagId, 'files');
-
- if (empty($fileIds)) {
- // This tag has no files, nothing can ever show up
- return [];
- }
-
- // first run ?
- if ($resultFileIds === null) {
- $resultFileIds = $fileIds;
- } else {
- $resultFileIds = array_intersect($resultFileIds, $fileIds);
- }
-
- if (empty($resultFileIds)) {
- // Empty intersection, nothing can show up anymore
- return [];
- }
- }
- return $resultFileIds;
- }
-
- /**
- * Prepare propfind response for the given nodes
- *
- * @param string[] $requestedProps requested properties
- * @param Node[] nodes nodes for which to fetch and prepare responses
- * @return Response[]
- */
- public function prepareResponses($requestedProps, $nodes) {
- $responses = [];
- foreach ($nodes as $node) {
- $propFind = new PropFind($node->getPath(), $requestedProps);
-
- $this->server->getPropertiesByNode($propFind, $node);
- // copied from Sabre Server's getPropertiesForPath
- $result = $propFind->getResultForMultiStatus();
- $result['href'] = $propFind->getPath();
-
- $resourceType = $this->server->getResourceTypeForNode($node);
- if (in_array('{DAV:}collection', $resourceType) || in_array('{DAV:}principal', $resourceType)) {
- $result['href'] .= '/';
- }
-
- $responses[] = new Response(
- rtrim($this->server->getBaseUri(), '/') . $node->getPath(),
- $result,
- 200
- );
- }
- return $responses;
- }
-
- /**
- * Find Sabre nodes by file ids
- *
- * @param Node $rootNode root node for search
- * @param array $fileIds file ids
- * @return Node[] array of Sabre nodes
- */
- public function findNodesByFileIds($rootNode, $fileIds) {
- $folder = $this->userFolder;
- if (trim($rootNode->getPath(), '/') !== '') {
- $folder = $folder->get($rootNode->getPath());
- }
-
- $results = [];
- foreach ($fileIds as $fileId) {
- $entry = $folder->getById($fileId);
- if ($entry) {
- $entry = current($entry);
- if ($entry instanceof \OCP\Files\File) {
- $results[] = new File($this->fileView, $entry);
- } else if ($entry instanceof \OCP\Files\Folder) {
- $results[] = new Directory($this->fileView, $entry);
- }
- }
- }
-
- return $results;
- }
-
- /**
- * Returns whether the currently logged in user is an administrator
- */
- private function isAdmin() {
- $user = $this->userSession->getUser();
- if ($user !== null) {
- return $this->groupManager->isAdmin($user->getUID());
- }
- return false;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/lockplugin.php b/apps/dav/lib/connector/sabre/lockplugin.php
deleted file mode 100644
index 66da39a57c8..00000000000
--- a/apps/dav/lib/connector/sabre/lockplugin.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCA\DAV\Connector\Sabre\Exception\FileLocked;
-use OCA\DAV\Connector\Sabre\Node;
-use OCP\Lock\ILockingProvider;
-use OCP\Lock\LockedException;
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\ServerPlugin;
-use Sabre\HTTP\RequestInterface;
-
-class LockPlugin extends ServerPlugin {
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * {@inheritdoc}
- */
- public function initialize(\Sabre\DAV\Server $server) {
- $this->server = $server;
- $this->server->on('beforeMethod', [$this, 'getLock'], 50);
- $this->server->on('afterMethod', [$this, 'releaseLock'], 50);
- }
-
- public function getLock(RequestInterface $request) {
- // we can't listen on 'beforeMethod:PUT' due to order of operations with setting up the tree
- // so instead we limit ourselves to the PUT method manually
- if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
- return;
- }
- try {
- $node = $this->server->tree->getNodeForPath($request->getPath());
- } catch (NotFound $e) {
- return;
- }
- if ($node instanceof Node) {
- try {
- $node->acquireLock(ILockingProvider::LOCK_SHARED);
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
- }
- }
-
- public function releaseLock(RequestInterface $request) {
- if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
- return;
- }
- try {
- $node = $this->server->tree->getNodeForPath($request->getPath());
- } catch (NotFound $e) {
- return;
- }
- if ($node instanceof Node) {
- $node->releaseLock(ILockingProvider::LOCK_SHARED);
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/maintenanceplugin.php b/apps/dav/lib/connector/sabre/maintenanceplugin.php
deleted file mode 100644
index 6e9a5930b78..00000000000
--- a/apps/dav/lib/connector/sabre/maintenanceplugin.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-/**
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\IConfig;
-use Sabre\DAV\Exception\ServiceUnavailable;
-use Sabre\DAV\ServerPlugin;
-
-class MaintenancePlugin extends ServerPlugin {
-
- /** @var IConfig */
- private $config;
-
- /**
- * Reference to main server object
- *
- * @var Server
- */
- private $server;
-
- /**
- * @param IConfig $config
- */
- public function __construct(IConfig $config = null) {
- $this->config = $config;
- if (is_null($config)) {
- $this->config = \OC::$server->getConfig();
- }
- }
-
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
- $this->server = $server;
- $this->server->on('beforeMethod', array($this, 'checkMaintenanceMode'), 1);
- }
-
- /**
- * This method is called before any HTTP method and returns http status code 503
- * in case the system is in maintenance mode.
- *
- * @throws ServiceUnavailable
- * @return bool
- */
- public function checkMaintenanceMode() {
- if ($this->config->getSystemValue('singleuser', false)) {
- throw new ServiceUnavailable('System in single user mode.');
- }
- if ($this->config->getSystemValue('maintenance', false)) {
- throw new ServiceUnavailable('System in maintenance mode.');
- }
- if (\OC::checkUpgrade(false)) {
- throw new ServiceUnavailable('Upgrade needed');
- }
-
- return true;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/node.php b/apps/dav/lib/connector/sabre/node.php
deleted file mode 100644
index ccc035063cd..00000000000
--- a/apps/dav/lib/connector/sabre/node.php
+++ /dev/null
@@ -1,348 +0,0 @@
-<?php
-/**
- * @author Arthur Schiwon <blizzz@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Klaas Freitag <freitag@owncloud.com>
- * @author Markus Goetz <markus@woboq.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OC\Files\Mount\MoveableMount;
-use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
-use OCP\Share\Exceptions\ShareNotFound;
-use OCP\Share\IManager;
-
-
-abstract class Node implements \Sabre\DAV\INode {
-
- /**
- * @var \OC\Files\View
- */
- protected $fileView;
-
- /**
- * The path to the current node
- *
- * @var string
- */
- protected $path;
-
- /**
- * node properties cache
- *
- * @var array
- */
- protected $property_cache = null;
-
- /**
- * @var \OCP\Files\FileInfo
- */
- protected $info;
-
- /**
- * @var IManager
- */
- protected $shareManager;
-
- /**
- * Sets up the node, expects a full path name
- *
- * @param \OC\Files\View $view
- * @param \OCP\Files\FileInfo $info
- * @param IManager $shareManager
- */
- public function __construct($view, $info, IManager $shareManager = null) {
- $this->fileView = $view;
- $this->path = $this->fileView->getRelativePath($info->getPath());
- $this->info = $info;
- if ($shareManager) {
- $this->shareManager = $shareManager;
- } else {
- $this->shareManager = \OC::$server->getShareManager();
- }
- }
-
- protected function refreshInfo() {
- $this->info = $this->fileView->getFileInfo($this->path);
- }
-
- /**
- * Returns the name of the node
- *
- * @return string
- */
- public function getName() {
- return $this->info->getName();
- }
-
- /**
- * Returns the full path
- *
- * @return string
- */
- public function getPath() {
- return $this->path;
- }
-
- /**
- * Renames the node
- *
- * @param string $name The new name
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws \Sabre\DAV\Exception\Forbidden
- */
- public function setName($name) {
-
- // rename is only allowed if the update privilege is granted
- if (!$this->info->isUpdateable()) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
-
- list($parentPath,) = \Sabre\HTTP\URLUtil::splitPath($this->path);
- list(, $newName) = \Sabre\HTTP\URLUtil::splitPath($name);
-
- // verify path of the target
- $this->verifyPath();
-
- $newPath = $parentPath . '/' . $newName;
-
- $this->fileView->rename($this->path, $newPath);
-
- $this->path = $newPath;
-
- $this->refreshInfo();
- }
-
- public function setPropertyCache($property_cache) {
- $this->property_cache = $property_cache;
- }
-
- /**
- * Returns the last modification time, as a unix timestamp
- *
- * @return int timestamp as integer
- */
- public function getLastModified() {
- $timestamp = $this->info->getMtime();
- if (!empty($timestamp)) {
- return (int)$timestamp;
- }
- return $timestamp;
- }
-
- /**
- * sets the last modification time of the file (mtime) to the value given
- * in the second parameter or to now if the second param is empty.
- * Even if the modification time is set to a custom value the access time is set to now.
- */
- public function touch($mtime) {
- $this->fileView->touch($this->path, $mtime);
- $this->refreshInfo();
- }
-
- /**
- * Returns the ETag for a file
- *
- * An ETag is a unique identifier representing the current version of the
- * file. If the file changes, the ETag MUST change. The ETag is an
- * arbitrary string, but MUST be surrounded by double-quotes.
- *
- * Return null if the ETag can not effectively be determined
- *
- * @return string
- */
- public function getETag() {
- return '"' . $this->info->getEtag() . '"';
- }
-
- /**
- * Sets the ETag
- *
- * @param string $etag
- *
- * @return int file id of updated file or -1 on failure
- */
- public function setETag($etag) {
- return $this->fileView->putFileInfo($this->path, array('etag' => $etag));
- }
-
- /**
- * Returns the size of the node, in bytes
- *
- * @return integer
- */
- public function getSize() {
- return $this->info->getSize();
- }
-
- /**
- * Returns the cache's file id
- *
- * @return int
- */
- public function getId() {
- return $this->info->getId();
- }
-
- /**
- * @return string|null
- */
- public function getFileId() {
- if ($this->info->getId()) {
- $instanceId = \OC_Util::getInstanceId();
- $id = sprintf('%08d', $this->info->getId());
- return $id . $instanceId;
- }
-
- return null;
- }
-
- /**
- * @return integer
- */
- public function getInternalFileId() {
- return $this->info->getId();
- }
-
- /**
- * @param string $user
- * @return int
- */
- public function getSharePermissions($user) {
-
- // check of we access a federated share
- if ($user !== null) {
- try {
- $share = $this->shareManager->getShareByToken($user);
- return $share->getPermissions();
- } catch (ShareNotFound $e) {
- // ignore
- }
- }
-
- $storage = $this->info->getStorage();
-
- $path = $this->info->getInternalPath();
-
- if ($storage->instanceOfStorage('\OC\Files\Storage\Shared')) {
- /** @var \OC\Files\Storage\Shared $storage */
- $permissions = (int)$storage->getShare()->getPermissions();
- } else {
- $permissions = $storage->getPermissions($path);
- }
-
- /*
- * We can always share non moveable mount points with DELETE and UPDATE
- * Eventually we need to do this properly
- */
- $mountpoint = $this->info->getMountPoint();
- if (!($mountpoint instanceof MoveableMount)) {
- $mountpointpath = $mountpoint->getMountPoint();
- if (substr($mountpointpath, -1) === '/') {
- $mountpointpath = substr($mountpointpath, 0, -1);
- }
-
- if ($mountpointpath === $this->info->getPath()) {
- $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
- }
- }
-
- /*
- * Files can't have create or delete permissions
- */
- if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
- $permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE);
- }
-
- return $permissions;
- }
-
- /**
- * @return string
- */
- public function getDavPermissions() {
- $p = '';
- if ($this->info->isShared()) {
- $p .= 'S';
- }
- if ($this->info->isShareable()) {
- $p .= 'R';
- }
- if ($this->info->isMounted()) {
- $p .= 'M';
- }
- if ($this->info->isDeletable()) {
- $p .= 'D';
- }
- if ($this->info->isUpdateable()) {
- $p .= 'NV'; // Renameable, Moveable
- }
- if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
- if ($this->info->isUpdateable()) {
- $p .= 'W';
- }
- } else {
- if ($this->info->isCreatable()) {
- $p .= 'CK';
- }
- }
- return $p;
- }
-
- public function getOwner() {
- return $this->info->getOwner();
- }
-
- protected function verifyPath() {
- try {
- $fileName = basename($this->info->getPath());
- $this->fileView->verifyPath($this->path, $fileName);
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- }
- }
-
- /**
- * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
- */
- public function acquireLock($type) {
- $this->fileView->lockFile($this->path, $type);
- }
-
- /**
- * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
- */
- public function releaseLock($type) {
- $this->fileView->unlockFile($this->path, $type);
- }
-
- /**
- * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
- */
- public function changeLock($type) {
- $this->fileView->changeLock($this->path, $type);
- }
-}
diff --git a/apps/dav/lib/connector/sabre/objecttree.php b/apps/dav/lib/connector/sabre/objecttree.php
deleted file mode 100644
index f38dfe679c7..00000000000
--- a/apps/dav/lib/connector/sabre/objecttree.php
+++ /dev/null
@@ -1,297 +0,0 @@
-<?php
-/**
- * @author Björn Schießle <schiessle@owncloud.com>
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCA\DAV\Connector\Sabre\Exception\Forbidden;
-use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
-use OCA\DAV\Connector\Sabre\Exception\FileLocked;
-use OC\Files\FileInfo;
-use OC\Files\Mount\MoveableMount;
-use OCP\Files\ForbiddenException;
-use OCP\Files\StorageInvalidException;
-use OCP\Files\StorageNotAvailableException;
-use OCP\Lock\LockedException;
-
-class ObjectTree extends \Sabre\DAV\Tree {
-
- /**
- * @var \OC\Files\View
- */
- protected $fileView;
-
- /**
- * @var \OCP\Files\Mount\IMountManager
- */
- protected $mountManager;
-
- /**
- * Creates the object
- */
- public function __construct() {
- }
-
- /**
- * @param \Sabre\DAV\INode $rootNode
- * @param \OC\Files\View $view
- * @param \OCP\Files\Mount\IMountManager $mountManager
- */
- public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\Files\Mount\IMountManager $mountManager) {
- $this->rootNode = $rootNode;
- $this->fileView = $view;
- $this->mountManager = $mountManager;
- }
-
- /**
- * If the given path is a chunked file name, converts it
- * to the real file name. Only applies if the OC-CHUNKED header
- * is present.
- *
- * @param string $path chunk file path to convert
- *
- * @return string path to real file
- */
- private function resolveChunkFile($path) {
- if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
- // resolve to real file name to find the proper node
- list($dir, $name) = \Sabre\HTTP\URLUtil::splitPath($path);
- if ($dir == '/' || $dir == '.') {
- $dir = '';
- }
-
- $info = \OC_FileChunking::decodeName($name);
- // only replace path if it was really the chunked file
- if (isset($info['transferid'])) {
- // getNodePath is called for multiple nodes within a chunk
- // upload call
- $path = $dir . '/' . $info['name'];
- $path = ltrim($path, '/');
- }
- }
- return $path;
- }
-
- public function cacheNode(Node $node) {
- $this->cache[trim($node->getPath(), '/')] = $node;
- }
-
- /**
- * Returns the INode object for the requested path
- *
- * @param string $path
- * @return \Sabre\DAV\INode
- * @throws InvalidPath
- * @throws \Sabre\DAV\Exception\Locked
- * @throws \Sabre\DAV\Exception\NotFound
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
- */
- public function getNodeForPath($path) {
- if (!$this->fileView) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
- }
-
- $path = trim($path, '/');
-
- if (isset($this->cache[$path])) {
- return $this->cache[$path];
- }
-
- if ($path) {
- try {
- $this->fileView->verifyPath($path, basename($path));
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- }
- }
-
- // Is it the root node?
- if (!strlen($path)) {
- return $this->rootNode;
- }
-
- if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
- // read from storage
- $absPath = $this->fileView->getAbsolutePath($path);
- $mount = $this->fileView->getMount($path);
- $storage = $mount->getStorage();
- $internalPath = $mount->getInternalPath($absPath);
- if ($storage && $storage->file_exists($internalPath)) {
- /**
- * @var \OC\Files\Storage\Storage $storage
- */
- // get data directly
- $data = $storage->getMetaData($internalPath);
- $info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
- } else {
- $info = null;
- }
- } else {
- // resolve chunk file name to real name, if applicable
- $path = $this->resolveChunkFile($path);
-
- // read from cache
- try {
- $info = $this->fileView->getFileInfo($path);
- } catch (StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage not available');
- } catch (StorageInvalidException $e) {
- throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
- } catch (LockedException $e) {
- throw new \Sabre\DAV\Exception\Locked();
- }
- }
-
- if (!$info) {
- throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
- }
-
- if ($info->getType() === 'dir') {
- $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this);
- } else {
- $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
- }
-
- $this->cache[$path] = $node;
- return $node;
-
- }
-
- /**
- * Moves a file from one location to another
- *
- * @param string $sourcePath The path to the file which should be moved
- * @param string $destinationPath The full destination path, so not just the destination parent node
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
- * @throws \Sabre\DAV\Exception\Forbidden
- * @return int
- */
- public function move($sourcePath, $destinationPath) {
- if (!$this->fileView) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
- }
-
- $targetNodeExists = $this->nodeExists($destinationPath);
- $sourceNode = $this->getNodeForPath($sourcePath);
- if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) {
- throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
- }
- list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($sourcePath);
- list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destinationPath);
-
- $isMovableMount = false;
- $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath));
- $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
- if ($sourceMount instanceof MoveableMount && $internalPath === '') {
- $isMovableMount = true;
- }
-
- try {
- $sameFolder = ($sourceDir === $destinationDir);
- // if we're overwriting or same folder
- if ($targetNodeExists || $sameFolder) {
- // note that renaming a share mount point is always allowed
- if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
- } else {
- if (!$this->fileView->isCreatable($destinationDir)) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
- }
-
- if (!$sameFolder) {
- // moving to a different folder, source will be gone, like a deletion
- // note that moving a share mount point is always allowed
- if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
- throw new \Sabre\DAV\Exception\Forbidden();
- }
- }
-
- $fileName = basename($destinationPath);
- try {
- $this->fileView->verifyPath($destinationDir, $fileName);
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- }
-
- $renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
- if (!$renameOkay) {
- throw new \Sabre\DAV\Exception\Forbidden('');
- }
- } catch (StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
- } catch (ForbiddenException $ex) {
- throw new Forbidden($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
-
- $this->markDirty($sourceDir);
- $this->markDirty($destinationDir);
-
- }
-
- /**
- * Copies a file or directory.
- *
- * This method must work recursively and delete the destination
- * if it exists
- *
- * @param string $source
- * @param string $destination
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
- * @return void
- */
- public function copy($source, $destination) {
- if (!$this->fileView) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
- }
-
- // this will trigger existence check
- $this->getNodeForPath($source);
-
- list($destinationDir, $destinationName) = \Sabre\HTTP\URLUtil::splitPath($destination);
- try {
- $this->fileView->verifyPath($destinationDir, $destinationName);
- } catch (\OCP\Files\InvalidPathException $ex) {
- throw new InvalidPath($ex->getMessage());
- }
-
- try {
- $this->fileView->copy($source, $destination);
- } catch (StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
- } catch (ForbiddenException $ex) {
- throw new Forbidden($ex->getMessage(), $ex->getRetry());
- } catch (LockedException $e) {
- throw new FileLocked($e->getMessage(), $e->getCode(), $e);
- }
-
- list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
- $this->markDirty($destinationDir);
- }
-}
diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php
deleted file mode 100644
index 787bcdf469b..00000000000
--- a/apps/dav/lib/connector/sabre/principal.php
+++ /dev/null
@@ -1,234 +0,0 @@
-<?php
-/**
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCP\IGroup;
-use OCP\IGroupManager;
-use OCP\IUser;
-use OCP\IUserManager;
-use Sabre\DAV\Exception;
-use \Sabre\DAV\PropPatch;
-use Sabre\DAVACL\PrincipalBackend\BackendInterface;
-use Sabre\HTTP\URLUtil;
-
-class Principal implements BackendInterface {
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var IGroupManager */
- private $groupManager;
-
- /** @var string */
- private $principalPrefix;
-
- /** @var bool */
- private $hasGroups;
-
- /**
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- * @param string $principalPrefix
- */
- public function __construct(IUserManager $userManager,
- IGroupManager $groupManager,
- $principalPrefix = 'principals/users/') {
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
- $this->principalPrefix = trim($principalPrefix, '/');
- $this->hasGroups = ($principalPrefix === 'principals/users/');
- }
-
- /**
- * Returns a list of principals based on a prefix.
- *
- * This prefix will often contain something like 'principals'. You are only
- * expected to return principals that are in this base path.
- *
- * You are expected to return at least a 'uri' for every user, you can
- * return any additional properties if you wish so. Common properties are:
- * {DAV:}displayname
- *
- * @param string $prefixPath
- * @return string[]
- */
- public function getPrincipalsByPrefix($prefixPath) {
- $principals = [];
-
- if ($prefixPath === $this->principalPrefix) {
- foreach($this->userManager->search('') as $user) {
- $principals[] = $this->userToPrincipal($user);
- }
- }
-
- return $principals;
- }
-
- /**
- * Returns a specific principal, specified by it's path.
- * The returned structure should be the exact same as from
- * getPrincipalsByPrefix.
- *
- * @param string $path
- * @return array
- */
- public function getPrincipalByPath($path) {
- list($prefix, $name) = URLUtil::splitPath($path);
-
- if ($prefix === $this->principalPrefix) {
- $user = $this->userManager->get($name);
-
- if (!is_null($user)) {
- return $this->userToPrincipal($user);
- }
- }
- return null;
- }
-
- /**
- * Returns the list of members for a group-principal
- *
- * @param string $principal
- * @return string[]
- * @throws Exception
- */
- public function getGroupMemberSet($principal) {
- // TODO: for now the group principal has only one member, the user itself
- $principal = $this->getPrincipalByPath($principal);
- if (!$principal) {
- throw new Exception('Principal not found');
- }
-
- return [$principal['uri']];
- }
-
- /**
- * Returns the list of groups a principal is a member of
- *
- * @param string $principal
- * @param bool $needGroups
- * @return array
- * @throws Exception
- */
- public function getGroupMembership($principal, $needGroups = false) {
- list($prefix, $name) = URLUtil::splitPath($principal);
-
- if ($prefix === $this->principalPrefix) {
- $user = $this->userManager->get($name);
- if (!$user) {
- throw new Exception('Principal not found');
- }
-
- if ($this->hasGroups || $needGroups) {
- $groups = $this->groupManager->getUserGroups($user);
- $groups = array_map(function($group) {
- /** @var IGroup $group */
- return 'principals/groups/' . $group->getGID();
- }, $groups);
-
- return $groups;
- }
- }
- return [];
- }
-
- /**
- * Updates the list of group members for a group principal.
- *
- * The principals should be passed as a list of uri's.
- *
- * @param string $principal
- * @param string[] $members
- * @throws Exception
- */
- public function setGroupMemberSet($principal, array $members) {
- throw new Exception('Setting members of the group is not supported yet');
- }
-
- /**
- * @param string $path
- * @param PropPatch $propPatch
- * @return int
- */
- function updatePrincipal($path, PropPatch $propPatch) {
- return 0;
- }
-
- /**
- * @param string $prefixPath
- * @param array $searchProperties
- * @param string $test
- * @return array
- */
- function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
- return [];
- }
-
- /**
- * @param string $uri
- * @param string $principalPrefix
- * @return string
- */
- function findByUri($uri, $principalPrefix) {
- if (substr($uri, 0, 7) === 'mailto:') {
- $email = substr($uri, 7);
- $users = $this->userManager->getByEmail($email);
- if (count($users) === 1) {
- return $this->principalPrefix . '/' . $users[0]->getUID();
- }
- }
-
- return '';
- }
-
- /**
- * @param IUser $user
- * @return array
- */
- protected function userToPrincipal($user) {
- $userId = $user->getUID();
- $displayName = $user->getDisplayName();
- $principal = [
- 'uri' => $this->principalPrefix . '/' . $userId,
- '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
- ];
-
- $email = $user->getEMailAddress();
- if (!empty($email)) {
- $principal['{http://sabredav.org/ns}email-address'] = $email;
- return $principal;
- }
- return $principal;
- }
-
- public function getPrincipalPrefix() {
- return $this->principalPrefix;
- }
-
-}
diff --git a/apps/dav/lib/connector/sabre/quotaplugin.php b/apps/dav/lib/connector/sabre/quotaplugin.php
deleted file mode 100644
index a093c52851c..00000000000
--- a/apps/dav/lib/connector/sabre/quotaplugin.php
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-/**
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author scambra <sergio@entrecables.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre;
-
-/**
- * This plugin check user quota and deny creating files when they exceeds the quota.
- *
- * @author Sergio Cambra
- * @copyright Copyright (C) 2012 entreCables S.L. All rights reserved.
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
-
- /**
- * @var \OC\Files\View
- */
- private $view;
-
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @param \OC\Files\View $view
- */
- public function __construct($view) {
- $this->view = $view;
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the requires event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
-
- $this->server = $server;
-
- $server->on('beforeWriteContent', array($this, 'checkQuota'), 10);
- $server->on('beforeCreateFile', array($this, 'checkQuota'), 10);
- }
-
- /**
- * This method is called before any HTTP method and validates there is enough free space to store the file
- *
- * @param string $uri
- * @param null $data
- * @throws \Sabre\DAV\Exception\InsufficientStorage
- * @return bool
- */
- public function checkQuota($uri, $data = null) {
- $length = $this->getLength();
- if ($length) {
- if (substr($uri, 0, 1) !== '/') {
- $uri = '/' . $uri;
- }
- list($parentUri, $newName) = \Sabre\HTTP\URLUtil::splitPath($uri);
- if(is_null($parentUri)) {
- $parentUri = '';
- }
- $req = $this->server->httpRequest;
- if ($req->getHeader('OC-Chunked')) {
- $info = \OC_FileChunking::decodeName($newName);
- $chunkHandler = $this->getFileChunking($info);
- // subtract the already uploaded size to see whether
- // there is still enough space for the remaining chunks
- $length -= $chunkHandler->getCurrentSize();
- // use target file name for free space check in case of shared files
- $uri = rtrim($parentUri, '/') . '/' . $info['name'];
- }
- $freeSpace = $this->getFreeSpace($uri);
- if ($freeSpace !== \OCP\Files\FileInfo::SPACE_UNKNOWN && $length > $freeSpace) {
- if (isset($chunkHandler)) {
- $chunkHandler->cleanup();
- }
- throw new \Sabre\DAV\Exception\InsufficientStorage();
- }
- }
- return true;
- }
-
- public function getFileChunking($info) {
- // FIXME: need a factory for better mocking support
- return new \OC_FileChunking($info);
- }
-
- public function getLength() {
- $req = $this->server->httpRequest;
- $length = $req->getHeader('X-Expected-Entity-Length');
- if (!$length) {
- $length = $req->getHeader('Content-Length');
- }
-
- $ocLength = $req->getHeader('OC-Total-Length');
- if ($length && $ocLength) {
- return max($length, $ocLength);
- }
-
- return $length;
- }
-
- /**
- * @param string $uri
- * @return mixed
- */
- public function getFreeSpace($uri) {
- try {
- $freeSpace = $this->view->free_space(ltrim($uri, '/'));
- return $freeSpace;
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/server.php b/apps/dav/lib/connector/sabre/server.php
deleted file mode 100644
index 421fc64422d..00000000000
--- a/apps/dav/lib/connector/sabre/server.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author scolebrook <scolebrook@mac.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-/**
- * Class \OCA\DAV\Connector\Sabre\Server
- *
- * This class overrides some methods from @see \Sabre\DAV\Server.
- *
- * @see \Sabre\DAV\Server
- */
-class Server extends \Sabre\DAV\Server {
-
- /**
- * @see \Sabre\DAV\Server
- */
- public function __construct($treeOrNode = null) {
- parent::__construct($treeOrNode);
- self::$exposeVersion = false;
- $this->enablePropfindDepthInfinity = true;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php
deleted file mode 100644
index 5853370778d..00000000000
--- a/apps/dav/lib/connector/sabre/serverfactory.php
+++ /dev/null
@@ -1,184 +0,0 @@
-<?php
-/**
- * @author Arthur Schiwon <blizzz@owncloud.com>
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use OCA\DAV\Files\BrowserErrorPagePlugin;
-use OCP\Files\Mount\IMountManager;
-use OCP\IConfig;
-use OCP\IDBConnection;
-use OCP\ILogger;
-use OCP\IRequest;
-use OCP\ITagManager;
-use OCP\IUserSession;
-use Sabre\DAV\Auth\Backend\BackendInterface;
-
-class ServerFactory {
- /** @var IConfig */
- private $config;
- /** @var ILogger */
- private $logger;
- /** @var IDBConnection */
- private $databaseConnection;
- /** @var IUserSession */
- private $userSession;
- /** @var IMountManager */
- private $mountManager;
- /** @var ITagManager */
- private $tagManager;
- /** @var IRequest */
- private $request;
-
- /**
- * @param IConfig $config
- * @param ILogger $logger
- * @param IDBConnection $databaseConnection
- * @param IUserSession $userSession
- * @param IMountManager $mountManager
- * @param ITagManager $tagManager
- * @param IRequest $request
- */
- public function __construct(
- IConfig $config,
- ILogger $logger,
- IDBConnection $databaseConnection,
- IUserSession $userSession,
- IMountManager $mountManager,
- ITagManager $tagManager,
- IRequest $request
- ) {
- $this->config = $config;
- $this->logger = $logger;
- $this->databaseConnection = $databaseConnection;
- $this->userSession = $userSession;
- $this->mountManager = $mountManager;
- $this->tagManager = $tagManager;
- $this->request = $request;
- }
-
- /**
- * @param string $baseUri
- * @param string $requestUri
- * @param BackendInterface $authBackend
- * @param callable $viewCallBack callback that should return the view for the dav endpoint
- * @return Server
- */
- public function createServer($baseUri,
- $requestUri,
- BackendInterface $authBackend,
- callable $viewCallBack) {
- // Fire up server
- $objectTree = new \OCA\DAV\Connector\Sabre\ObjectTree();
- $server = new \OCA\DAV\Connector\Sabre\Server($objectTree);
- // Set URL explicitly due to reverse-proxy situations
- $server->httpRequest->setUrl($requestUri);
- $server->setBaseUri($baseUri);
-
- // Load plugins
- $defaults = new \OC_Defaults();
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin($this->config));
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin($this->config));
- $server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, $defaults->getName()));
- // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin());
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger));
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin());
- // Some WebDAV clients do require Class 2 WebDAV support (locking), since
- // we do not provide locking we emulate it using a fake locking plugin.
- if($this->request->isUserAgent([
- '/WebDAVFS/',
- '/Microsoft Office OneNote 2013/',
- '/Microsoft-WebDAV-MiniRedir/',
- ])) {
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin());
- }
-
- if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
- $server->addPlugin(new BrowserErrorPagePlugin());
- }
-
- // wait with registering these until auth is handled and the filesystem is setup
- $server->on('beforeMethod', function () use ($server, $objectTree, $viewCallBack) {
- // ensure the skeleton is copied
- $userFolder = \OC::$server->getUserFolder();
-
- /** @var \OC\Files\View $view */
- $view = $viewCallBack($server);
- $rootInfo = $view->getFileInfo('');
-
- // Create ownCloud Dir
- if ($rootInfo->getType() === 'dir') {
- $root = new \OCA\DAV\Connector\Sabre\Directory($view, $rootInfo, $objectTree);
- } else {
- $root = new \OCA\DAV\Connector\Sabre\File($view, $rootInfo);
- }
- $objectTree->init($root, $view, $this->mountManager);
-
- $server->addPlugin(
- new \OCA\DAV\Connector\Sabre\FilesPlugin(
- $objectTree,
- $view,
- $this->config,
- false,
- !$this->config->getSystemValue('debug', false)
- )
- );
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\QuotaPlugin($view));
-
- if($this->userSession->isLoggedIn()) {
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\TagsPlugin($objectTree, $this->tagManager));
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\SharesPlugin(
- $objectTree,
- $this->userSession,
- $userFolder,
- \OC::$server->getShareManager()
- ));
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\CommentPropertiesPlugin(\OC::$server->getCommentsManager(), $this->userSession));
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesReportPlugin(
- $objectTree,
- $view,
- \OC::$server->getSystemTagManager(),
- \OC::$server->getSystemTagObjectMapper(),
- $this->userSession,
- \OC::$server->getGroupManager(),
- $userFolder
- ));
- // custom properties plugin must be the last one
- $server->addPlugin(
- new \Sabre\DAV\PropertyStorage\Plugin(
- new \OCA\DAV\Connector\Sabre\CustomPropertiesBackend(
- $objectTree,
- $this->databaseConnection,
- $this->userSession->getUser()
- )
- )
- );
- }
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\CopyEtagHeaderPlugin());
- }, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
- return $server;
- }
-}
diff --git a/apps/dav/lib/connector/sabre/sharesplugin.php b/apps/dav/lib/connector/sabre/sharesplugin.php
deleted file mode 100644
index c76068969e9..00000000000
--- a/apps/dav/lib/connector/sabre/sharesplugin.php
+++ /dev/null
@@ -1,177 +0,0 @@
-<?php
-/**
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre;
-
-use \Sabre\DAV\PropFind;
-use \Sabre\DAV\PropPatch;
-use OCP\IUserSession;
-use OCP\Share\IShare;
-use OCA\DAV\Connector\Sabre\ShareTypeList;
-
-/**
- * Sabre Plugin to provide share-related properties
- */
-class SharesPlugin extends \Sabre\DAV\ServerPlugin {
-
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
- const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
-
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \OCP\Share\IManager
- */
- private $shareManager;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var string
- */
- private $userId;
-
- /**
- * @var \OCP\Files\Folder
- */
- private $userFolder;
-
- /**
- * @var IShare[]
- */
- private $cachedShareTypes;
-
- /**
- * @param \Sabre\DAV\Tree $tree tree
- * @param IUserSession $userSession user session
- * @param \OCP\Files\Folder $userFolder user home folder
- * @param \OCP\Share\IManager $shareManager share manager
- */
- public function __construct(
- \Sabre\DAV\Tree $tree,
- IUserSession $userSession,
- \OCP\Files\Folder $userFolder,
- \OCP\Share\IManager $shareManager
- ) {
- $this->tree = $tree;
- $this->shareManager = $shareManager;
- $this->userFolder = $userFolder;
- $this->userId = $userSession->getUser()->getUID();
- $this->cachedShareTypes = [];
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- */
- public function initialize(\Sabre\DAV\Server $server) {
- $server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
- $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = 'OCA\\DAV\\Connector\\Sabre\\ShareTypeList';
- $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
-
- $this->server = $server;
- $this->server->on('propFind', array($this, 'handleGetProperties'));
- }
-
- /**
- * Return a list of share types for outgoing shares
- *
- * @param \OCP\Files\Node $node file node
- *
- * @return int[] array of share types
- */
- private function getShareTypes(\OCP\Files\Node $node) {
- $shareTypes = [];
- $requestedShareTypes = [
- \OCP\Share::SHARE_TYPE_USER,
- \OCP\Share::SHARE_TYPE_GROUP,
- \OCP\Share::SHARE_TYPE_LINK,
- \OCP\Share::SHARE_TYPE_REMOTE
- ];
- foreach ($requestedShareTypes as $requestedShareType) {
- // one of each type is enough to find out about the types
- $shares = $this->shareManager->getSharesBy(
- $this->userId,
- $requestedShareType,
- $node,
- false,
- 1
- );
- if (!empty($shares)) {
- $shareTypes[] = $requestedShareType;
- }
- }
- return $shareTypes;
- }
-
- /**
- * Adds shares to propfind response
- *
- * @param PropFind $propFind propfind object
- * @param \Sabre\DAV\INode $sabreNode sabre node
- */
- public function handleGetProperties(
- PropFind $propFind,
- \Sabre\DAV\INode $sabreNode
- ) {
- if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
- return;
- }
-
- // need prefetch ?
- if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
- && $propFind->getDepth() !== 0
- && !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME))
- ) {
- $folderNode = $this->userFolder->get($propFind->getPath());
- $children = $folderNode->getDirectoryListing();
-
- $this->cachedShareTypes[$folderNode->getId()] = $this->getShareTypes($folderNode);
- foreach ($children as $childNode) {
- $this->cachedShareTypes[$childNode->getId()] = $this->getShareTypes($childNode);
- }
- }
-
- $propFind->handle(self::SHARETYPES_PROPERTYNAME, function() use ($sabreNode) {
- if (isset($this->cachedShareTypes[$sabreNode->getId()])) {
- $shareTypes = $this->cachedShareTypes[$sabreNode->getId()];
- } else {
- $node = $this->userFolder->get($sabreNode->getPath());
- $shareTypes = $this->getShareTypes($node);
- }
-
- return new ShareTypeList($shareTypes);
- });
- }
-}
diff --git a/apps/dav/lib/connector/sabre/sharetypelist.php b/apps/dav/lib/connector/sabre/sharetypelist.php
deleted file mode 100644
index 763586412ad..00000000000
--- a/apps/dav/lib/connector/sabre/sharetypelist.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use Sabre\Xml\Element;
-use Sabre\Xml\Reader;
-use Sabre\Xml\Writer;
-
-/**
- * ShareTypeList property
- *
- * This property contains multiple "share-type" elements, each containing a share type.
- */
-class ShareTypeList implements Element {
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
-
- /**
- * Share types
- *
- * @var int[]
- */
- private $shareTypes;
-
- /**
- * @param int[] $shareTypes
- */
- public function __construct($shareTypes) {
- $this->shareTypes = $shareTypes;
- }
-
- /**
- * Returns the share types
- *
- * @return int[]
- */
- public function getShareTypes() {
- return $this->shareTypes;
- }
-
- /**
- * The deserialize method is called during xml parsing.
- *
- * @param Reader $reader
- * @return mixed
- */
- static function xmlDeserialize(Reader $reader) {
- $shareTypes = [];
-
- foreach ($reader->parseInnerTree() as $elem) {
- if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}share-type') {
- $shareTypes[] = (int)$elem['value'];
- }
- }
- return new self($shareTypes);
- }
-
- /**
- * The xmlSerialize metod is called during xml writing.
- *
- * @param Writer $writer
- * @return void
- */
- function xmlSerialize(Writer $writer) {
- foreach ($this->shareTypes as $shareType) {
- $writer->writeElement('{' . self::NS_OWNCLOUD . '}share-type', $shareType);
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/taglist.php b/apps/dav/lib/connector/sabre/taglist.php
deleted file mode 100644
index 5c1cd8b4f1d..00000000000
--- a/apps/dav/lib/connector/sabre/taglist.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-
-namespace OCA\DAV\Connector\Sabre;
-
-use Sabre\Xml\Element;
-use Sabre\Xml\Reader;
-use Sabre\Xml\Writer;
-
-/**
- * TagList property
- *
- * This property contains multiple "tag" elements, each containing a tag name.
- */
-class TagList implements Element {
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
-
- /**
- * tags
- *
- * @var array
- */
- private $tags;
-
- /**
- * @param array $tags
- */
- public function __construct(array $tags) {
- $this->tags = $tags;
- }
-
- /**
- * Returns the tags
- *
- * @return array
- */
- public function getTags() {
-
- return $this->tags;
-
- }
-
- /**
- * The deserialize method is called during xml parsing.
- *
- * This method is called statictly, this is because in theory this method
- * may be used as a type of constructor, or factory method.
- *
- * Often you want to return an instance of the current class, but you are
- * free to return other data as well.
- *
- * You are responsible for advancing the reader to the next element. Not
- * doing anything will result in a never-ending loop.
- *
- * If you just want to skip parsing for this element altogether, you can
- * just call $reader->next();
- *
- * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
- * the next element.
- *
- * @param Reader $reader
- * @return mixed
- */
- static function xmlDeserialize(Reader $reader) {
- $tags = [];
-
- foreach ($reader->parseInnerTree() as $elem) {
- if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}tag') {
- $tags[] = $elem['value'];
- }
- }
- return new self($tags);
- }
-
- /**
- * The xmlSerialize metod is called during xml writing.
- *
- * Use the $writer argument to write its own xml serialization.
- *
- * An important note: do _not_ create a parent element. Any element
- * implementing XmlSerializble should only ever write what's considered
- * its 'inner xml'.
- *
- * The parent of the current element is responsible for writing a
- * containing element.
- *
- * This allows serializers to be re-used for different element names.
- *
- * If you are opening new elements, you must also close them again.
- *
- * @param Writer $writer
- * @return void
- */
- function xmlSerialize(Writer $writer) {
-
- foreach ($this->tags as $tag) {
- $writer->writeElement('{' . self::NS_OWNCLOUD . '}tag', $tag);
- }
- }
-}
diff --git a/apps/dav/lib/connector/sabre/tagsplugin.php b/apps/dav/lib/connector/sabre/tagsplugin.php
deleted file mode 100644
index dfc1a2dd95d..00000000000
--- a/apps/dav/lib/connector/sabre/tagsplugin.php
+++ /dev/null
@@ -1,293 +0,0 @@
-<?php
-/**
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2016, 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/>
- *
- */
-namespace OCA\DAV\Connector\Sabre;
-
-/**
- * ownCloud
- *
- * @author Vincent Petry
- * @copyright 2014 Vincent Petry <pvince81@owncloud.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-use \Sabre\DAV\PropFind;
-use \Sabre\DAV\PropPatch;
-
-class TagsPlugin extends \Sabre\DAV\ServerPlugin
-{
-
- // namespace
- const NS_OWNCLOUD = 'http://owncloud.org/ns';
- const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags';
- const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite';
- const TAG_FAVORITE = '_$!<Favorite>!$_';
-
- /**
- * Reference to main server object
- *
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \OCP\ITagManager
- */
- private $tagManager;
-
- /**
- * @var \OCP\ITags
- */
- private $tagger;
-
- /**
- * Array of file id to tags array
- * The null value means the cache wasn't initialized.
- *
- * @var array
- */
- private $cachedTags;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @param \Sabre\DAV\Tree $tree tree
- * @param \OCP\ITagManager $tagManager tag manager
- */
- public function __construct(\Sabre\DAV\Tree $tree, \OCP\ITagManager $tagManager) {
- $this->tree = $tree;
- $this->tagManager = $tagManager;
- $this->tagger = null;
- $this->cachedTags = array();
- }
-
- /**
- * This initializes the plugin.
- *
- * This function is called by \Sabre\DAV\Server, after
- * addPlugin is called.
- *
- * This method should set up the required event subscriptions.
- *
- * @param \Sabre\DAV\Server $server
- * @return void
- */
- public function initialize(\Sabre\DAV\Server $server) {
-
- $server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
- $server->xml->elementMap[self::TAGS_PROPERTYNAME] = 'OCA\\DAV\\Connector\\Sabre\\TagList';
-
- $this->server = $server;
- $this->server->on('propFind', array($this, 'handleGetProperties'));
- $this->server->on('propPatch', array($this, 'handleUpdateProperties'));
- }
-
- /**
- * Returns the tagger
- *
- * @return \OCP\ITags tagger
- */
- private function getTagger() {
- if (!$this->tagger) {
- $this->tagger = $this->tagManager->load('files');
- }
- return $this->tagger;
- }
-
- /**
- * Returns tags and favorites.
- *
- * @param integer $fileId file id
- * @return array list($tags, $favorite) with $tags as tag array
- * and $favorite is a boolean whether the file was favorited
- */
- private function getTagsAndFav($fileId) {
- $isFav = false;
- $tags = $this->getTags($fileId);
- if ($tags) {
- $favPos = array_search(self::TAG_FAVORITE, $tags);
- if ($favPos !== false) {
- $isFav = true;
- unset($tags[$favPos]);
- }
- }
- return array($tags, $isFav);
- }
-
- /**
- * Returns tags for the given file id
- *
- * @param integer $fileId file id
- * @return array list of tags for that file
- */
- private function getTags($fileId) {
- if (isset($this->cachedTags[$fileId])) {
- return $this->cachedTags[$fileId];
- } else {
- $tags = $this->getTagger()->getTagsForObjects(array($fileId));
- if ($tags !== false) {
- if (empty($tags)) {
- return array();
- }
- return current($tags);
- }
- }
- return null;
- }
-
- /**
- * Updates the tags of the given file id
- *
- * @param int $fileId
- * @param array $tags array of tag strings
- */
- private function updateTags($fileId, $tags) {
- $tagger = $this->getTagger();
- $currentTags = $this->getTags($fileId);
-
- $newTags = array_diff($tags, $currentTags);
- foreach ($newTags as $tag) {
- if ($tag === self::TAG_FAVORITE) {
- continue;
- }
- $tagger->tagAs($fileId, $tag);
- }
- $deletedTags = array_diff($currentTags, $tags);
- foreach ($deletedTags as $tag) {
- if ($tag === self::TAG_FAVORITE) {
- continue;
- }
- $tagger->unTag($fileId, $tag);
- }
- }
-
- /**
- * Adds tags and favorites properties to the response,
- * if requested.
- *
- * @param PropFind $propFind
- * @param \Sabre\DAV\INode $node
- * @return void
- */
- public function handleGetProperties(
- PropFind $propFind,
- \Sabre\DAV\INode $node
- ) {
- if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
- return;
- }
-
- // need prefetch ?
- if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
- && $propFind->getDepth() !== 0
- && (!is_null($propFind->getStatus(self::TAGS_PROPERTYNAME))
- || !is_null($propFind->getStatus(self::FAVORITE_PROPERTYNAME))
- )) {
- // note: pre-fetching only supported for depth <= 1
- $folderContent = $node->getChildren();
- $fileIds[] = (int)$node->getId();
- foreach ($folderContent as $info) {
- $fileIds[] = (int)$info->getId();
- }
- $tags = $this->getTagger()->getTagsForObjects($fileIds);
- if ($tags === false) {
- // the tags API returns false on error...
- $tags = array();
- }
-
- $this->cachedTags = $this->cachedTags + $tags;
- $emptyFileIds = array_diff($fileIds, array_keys($tags));
- // also cache the ones that were not found
- foreach ($emptyFileIds as $fileId) {
- $this->cachedTags[$fileId] = [];
- }
- }
-
- $tags = null;
- $isFav = null;
-
- $propFind->handle(self::TAGS_PROPERTYNAME, function() use ($tags, &$isFav, $node) {
- list($tags, $isFav) = $this->getTagsAndFav($node->getId());
- return new TagList($tags);
- });
-
- $propFind->handle(self::FAVORITE_PROPERTYNAME, function() use ($isFav, $node) {
- if (is_null($isFav)) {
- list(, $isFav) = $this->getTagsAndFav($node->getId());
- }
- return $isFav;
- });
- }
-
- /**
- * Updates tags and favorites properties, if applicable.
- *
- * @param string $path
- * @param PropPatch $propPatch
- *
- * @return void
- */
- public function handleUpdateProperties($path, PropPatch $propPatch) {
- $propPatch->handle(self::TAGS_PROPERTYNAME, function($tagList) use ($path) {
- $node = $this->tree->getNodeForPath($path);
- if (is_null($node)) {
- return 404;
- }
- $this->updateTags($node->getId(), $tagList->getTags());
- return true;
- });
-
- $propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($path) {
- $node = $this->tree->getNodeForPath($path);
- if (is_null($node)) {
- return 404;
- }
- if ((int)$favState === 1 || $favState === 'true') {
- $this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
- } else {
- $this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
- }
-
- if (is_null($favState)) {
- // confirm deletion
- return 204;
- }
-
- return 200;
- });
- }
-}