[Pkg-owncloud-commits] [owncloud] 02/107: [stable8.2] Add fake locker plugin
David Prévot
taffit at moszumanska.debian.org
Thu Dec 17 19:40:29 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch stable8
in repository owncloud.
commit 5641e4c103c9fb446a221576dd91f1ba2b8d8453
Author: Lukas Reschke <lukas at owncloud.com>
Date: Mon Nov 16 15:03:59 2015 +0100
[stable8.2] Add fake locker plugin
---
apps/files/appinfo/remote.php | 3 +-
apps/files_sharing/publicwebdav.php | 3 +-
lib/private/connector/sabre/fakelockerplugin.php | 159 +++++++++++++++++++
lib/private/connector/sabre/serverfactory.php | 38 ++++-
tests/lib/connector/sabre/FakeLockerPluginTest.php | 173 +++++++++++++++++++++
.../connector/sabre/requesttest/requesttest.php | 3 +-
6 files changed, 375 insertions(+), 4 deletions(-)
diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php
index 02f7f3c..18f368c 100644
--- a/apps/files/appinfo/remote.php
+++ b/apps/files/appinfo/remote.php
@@ -39,7 +39,8 @@ $serverFactory = new \OC\Connector\Sabre\ServerFactory(
\OC::$server->getUserSession(),
\OC::$server->getMountManager(),
\OC::$server->getTagManager(),
- \OC::$server->getEventDispatcher()
+ \OC::$server->getEventDispatcher(),
+ \OC::$server->getRequest()
);
// Backends
diff --git a/apps/files_sharing/publicwebdav.php b/apps/files_sharing/publicwebdav.php
index 7d96c8e..a112d71 100644
--- a/apps/files_sharing/publicwebdav.php
+++ b/apps/files_sharing/publicwebdav.php
@@ -39,7 +39,8 @@ $serverFactory = new \OC\Connector\Sabre\ServerFactory(
\OC::$server->getUserSession(),
\OC::$server->getMountManager(),
\OC::$server->getTagManager(),
- \OC::$server->getEventDispatcher()
+ \OC::$server->getEventDispatcher(),
+ \OC::$server->getRequest()
);
$requestUri = \OC::$server->getRequest()->getRequestUri();
diff --git a/lib/private/connector/sabre/fakelockerplugin.php b/lib/private/connector/sabre/fakelockerplugin.php
new file mode 100644
index 0000000..8111dea
--- /dev/null
+++ b/lib/private/connector/sabre/fakelockerplugin.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas at owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Connector\Sabre;
+
+use Sabre\DAV\Locks\LockInfo;
+use Sabre\DAV\Property\LockDiscovery;
+use Sabre\DAV\Property\SupportedLock;
+use Sabre\DAV\ServerPlugin;
+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 OC\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 array
+ */
+ public function getHTTPMethods($path) {
+ return [
+ 'LOCK',
+ 'UNLOCK',
+ ];
+ }
+
+ /**
+ * Indicate that we support locking
+ *
+ * @return array
+ */
+ 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) {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $prop = $dom->createElementNS('DAV:', 'd:prop');
+ $dom->appendChild($prop);
+
+ $lockDiscovery = $dom->createElementNS('DAV:', 'd:lockdiscovery');
+ $prop->appendChild($lockDiscovery);
+
+ $lockInfo = new LockInfo();
+ $lockInfo->token = md5($request->getPath());
+ $lockInfo->uri = $request->getPath();
+ $lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
+ $lockInfo->timeout = 1800;
+
+ $lockObj = new LockDiscovery([$lockInfo]);
+ $lockObj->serialize($this->server, $lockDiscovery);
+
+ $response->setBody($dom->saveXML());
+
+ return false;
+ }
+
+ /**
+ * 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;
+ }
+}
\ No newline at end of file
diff --git a/lib/private/connector/sabre/serverfactory.php b/lib/private/connector/sabre/serverfactory.php
index 893e29f..a558a61 100644
--- a/lib/private/connector/sabre/serverfactory.php
+++ b/lib/private/connector/sabre/serverfactory.php
@@ -26,12 +26,40 @@ 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;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
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 EventDispatcherInterface */
+ private $dispatcher;
+ /** @var IRequest */
+ private $request;
+
+ /**
+ * @param IConfig $config
+ * @param ILogger $logger
+ * @param IDBConnection $databaseConnection
+ * @param IUserSession $userSession
+ * @param IMountManager $mountManager
+ * @param ITagManager $tagManager
+ * @param EventDispatcherInterface $dispatcher
+ * @param IRequest $request
+ */
public function __construct(
IConfig $config,
ILogger $logger,
@@ -39,7 +67,8 @@ class ServerFactory {
IUserSession $userSession,
IMountManager $mountManager,
ITagManager $tagManager,
- EventDispatcherInterface $dispatcher
+ EventDispatcherInterface $dispatcher,
+ IRequest $request
) {
$this->config = $config;
$this->logger = $logger;
@@ -48,6 +77,7 @@ class ServerFactory {
$this->mountManager = $mountManager;
$this->tagManager = $tagManager;
$this->dispatcher = $dispatcher;
+ $this->request = $request;
}
/**
@@ -76,6 +106,12 @@ class ServerFactory {
$server->addPlugin(new \OC\Connector\Sabre\LockPlugin($objectTree));
$server->addPlugin(new \OC\Connector\Sabre\ListenerPlugin($this->dispatcher));
+ // Finder on OS X requires Class 2 WebDAV support (locking), since we do
+ // not provide locking we emulate it using a fake locking plugin.
+ if($this->request->isUserAgent(['/WebDAVFS/'])) {
+ $server->addPlugin(new \OC\Connector\Sabre\FakeLockerPlugin());
+ }
+
// wait with registering these until auth is handled and the filesystem is setup
$server->on('beforeMethod', function () use ($server, $objectTree, $viewCallBack) {
/** @var \OC\Files\View $view */
diff --git a/tests/lib/connector/sabre/FakeLockerPluginTest.php b/tests/lib/connector/sabre/FakeLockerPluginTest.php
new file mode 100644
index 0000000..2dc6e73
--- /dev/null
+++ b/tests/lib/connector/sabre/FakeLockerPluginTest.php
@@ -0,0 +1,173 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas at owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\DAV\Tests\Unit\Connector\Sabre;
+
+use OC\Connector\Sabre\FakeLockerPlugin;
+use Test\TestCase;
+
+/**
+ * Class FakeLockerPluginTest
+ *
+ * @package OC\DAV\Tests\Unit\Connector\Sabre
+ */
+class FakeLockerPluginTest extends TestCase {
+ /** @var FakeLockerPlugin */
+ private $fakeLockerPlugin;
+
+ public function setUp() {
+ parent::setUp();
+ $this->fakeLockerPlugin = new FakeLockerPlugin();
+ }
+
+ public function testInitialize() {
+ /** @var \Sabre\DAV\Server $server */
+ $server = $this->getMock('\Sabre\DAV\Server');
+ $server
+ ->expects($this->at(0))
+ ->method('on')
+ ->with('method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1);
+ $server
+ ->expects($this->at(1))
+ ->method('on')
+ ->with('method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1);
+ $server
+ ->expects($this->at(2))
+ ->method('on')
+ ->with('propFind', [$this->fakeLockerPlugin, 'propFind']);
+ $server
+ ->expects($this->at(3))
+ ->method('on')
+ ->with('validateTokens', [$this->fakeLockerPlugin, 'validateTokens']);
+
+ $this->fakeLockerPlugin->initialize($server);
+ }
+
+ public function testGetHTTPMethods() {
+ $expected = [
+ 'LOCK',
+ 'UNLOCK',
+ ];
+ $this->assertSame($expected, $this->fakeLockerPlugin->getHTTPMethods('Test'));
+ }
+
+ public function testGetFeatures() {
+ $expected = [
+ 2,
+ ];
+ $this->assertSame($expected, $this->fakeLockerPlugin->getFeatures());
+ }
+
+ public function testPropFind() {
+ $propFind = $this->getMockBuilder('\Sabre\DAV\PropFind')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $node = $this->getMock('\Sabre\DAV\INode');
+
+ $propFind->expects($this->at(0))
+ ->method('handle')
+ ->with('{DAV:}supportedlock');
+ $propFind->expects($this->at(1))
+ ->method('handle')
+ ->with('{DAV:}lockdiscovery');
+
+ $this->fakeLockerPlugin->propFind($propFind, $node);
+ }
+
+ public function tokenDataProvider() {
+ return [
+ [
+ [
+ [
+ 'tokens' => [
+ [
+ 'token' => 'aToken',
+ 'validToken' => false,
+ ],
+ [],
+ [
+ 'token' => 'opaquelocktoken:asdf',
+ 'validToken' => false,
+ ]
+ ],
+ ]
+ ],
+ [
+ [
+ 'tokens' => [
+ [
+ 'token' => 'aToken',
+ 'validToken' => false,
+ ],
+ [],
+ [
+ 'token' => 'opaquelocktoken:asdf',
+ 'validToken' => true,
+ ]
+ ],
+ ]
+ ],
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider tokenDataProvider
+ * @param array $input
+ * @param array $expected
+ */
+ public function testValidateTokens(array $input, array $expected) {
+ $request = $this->getMock('\Sabre\HTTP\RequestInterface');
+ $this->fakeLockerPlugin->validateTokens($request, $input);
+ $this->assertSame($expected, $input);
+ }
+
+ public function testFakeLockProvider() {
+ $request = $this->getMock('\Sabre\HTTP\RequestInterface');
+ $response = $this->getMock('\Sabre\HTTP\ResponseInterface');
+ $server = $this->getMock('\Sabre\DAV\Server');
+ $this->fakeLockerPlugin->initialize($server);
+
+ $request->expects($this->exactly(2))
+ ->method('getPath')
+ ->will($this->returnValue('MyPath'));
+ $response->expects($this->once())
+ ->method('setBody')
+ ->with('<?xml version="1.0" encoding="utf-8"?>
+<d:prop xmlns:d="DAV:"><d:lockdiscovery><d:activelock><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype><d:lockroot><d:href>MyPath</d:href></d:lockroot><d:depth>infinity</d:depth><d:timeout>Second-1800</d:timeout><d:locktoken><d:href>opaquelocktoken:fe4f7f2437b151fbcb4e9f5c8118c6b1</d:href></d:locktoken><d:owner/></d:activelock></d:lockdiscovery></d:prop>
+');
+
+ $this->assertSame(false, $this->fakeLockerPlugin->fakeLockProvider($request, $response));
+ }
+
+ public function testFakeUnlockProvider() {
+ $request = $this->getMock('\Sabre\HTTP\RequestInterface');
+ $response = $this->getMock('\Sabre\HTTP\ResponseInterface');
+
+ $response->expects($this->once())
+ ->method('setStatus')
+ ->with('204');
+ $response->expects($this->once())
+ ->method('setHeader')
+ ->with('Content-Length', '0');
+
+ $this->assertSame(false, $this->fakeLockerPlugin->fakeUnlockProvider($request, $response));
+ }
+}
\ No newline at end of file
diff --git a/tests/lib/connector/sabre/requesttest/requesttest.php b/tests/lib/connector/sabre/requesttest/requesttest.php
index 4d4c817..225213c 100644
--- a/tests/lib/connector/sabre/requesttest/requesttest.php
+++ b/tests/lib/connector/sabre/requesttest/requesttest.php
@@ -46,7 +46,8 @@ abstract class RequestTest extends TestCase {
\OC::$server->getUserSession(),
\OC::$server->getMountManager(),
\OC::$server->getTagManager(),
- \OC::$server->getEventDispatcher()
+ \OC::$server->getEventDispatcher(),
+ $this->getMock('\OCP\IRequest')
);
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git
More information about the Pkg-owncloud-commits
mailing list