summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Reschke <lukas@owncloud.com>2016-02-25 20:46:01 +0100
committerLukas Reschke <lukas@owncloud.com>2016-02-26 09:26:55 +0100
commit59028cced0a4f7377de9c22012c7624440b14a56 (patch)
treedc209a35e1626309032640459bec268323e51bac
parentcb41b1a86397579d55e0ce96e67b80a83037d1d2 (diff)
downloadnextcloud-server-59028cced0a4f7377de9c22012c7624440b14a56.tar.gz
nextcloud-server-59028cced0a4f7377de9c22012c7624440b14a56.zip
Add autodiscovery support to server-to-server sharing
Adds autodiscovery support to server-to-server sharing as specified in the specification. If no discovery data is found it is using the fallback ownCloud endpoints for legacy support.
-rw-r--r--apps/federatedfilesharing/lib/discoverymanager.php134
-rw-r--r--apps/federatedfilesharing/lib/notifications.php36
-rw-r--r--apps/federatedfilesharing/tests/DiscoveryManagerTest.php194
-rw-r--r--apps/files_sharing/ajax/external.php5
-rw-r--r--apps/files_sharing/api/remote.php31
-rw-r--r--apps/files_sharing/api/server2server.php6
-rw-r--r--apps/files_sharing/appinfo/application.php6
-rw-r--r--apps/files_sharing/lib/external/manager.php18
-rw-r--r--apps/files_sharing/lib/external/storage.php8
-rw-r--r--apps/files_sharing/lib/hooks.php6
-rw-r--r--apps/files_sharing/tests/external/managertest.php6
-rw-r--r--apps/files_sharing/tests/server2server.php7
-rw-r--r--lib/private/share/constants.php2
-rw-r--r--lib/private/share/share.php25
-rw-r--r--lib/private/share20/providerfactory.php8
15 files changed, 456 insertions, 36 deletions
diff --git a/apps/federatedfilesharing/lib/discoverymanager.php b/apps/federatedfilesharing/lib/discoverymanager.php
new file mode 100644
index 00000000000..1df510438d7
--- /dev/null
+++ b/apps/federatedfilesharing/lib/discoverymanager.php
@@ -0,0 +1,134 @@
+<?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\FederatedFileSharing;
+
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\ConnectException;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+use OCP\ICache;
+use OCP\ICacheFactory;
+
+/**
+ * Class DiscoveryManager handles the discovery of endpoints used by Federated
+ * Cloud Sharing.
+ *
+ * @package OCA\FederatedFileSharing
+ */
+class DiscoveryManager {
+ /** @var ICache */
+ private $cache;
+ /** @var IClient */
+ private $client;
+
+ /**
+ * @param ICacheFactory $cacheFactory
+ * @param IClientService $clientService
+ */
+ public function __construct(ICacheFactory $cacheFactory,
+ IClientService $clientService) {
+ $this->cache = $cacheFactory->create('ocs-discovery');
+ $this->client = $clientService->newClient();
+ }
+
+ /**
+ * Returns whether the specified URL includes only safe characters, if not
+ * returns false
+ *
+ * @param string $url
+ * @return bool
+ */
+ private function isSafeUrl($url) {
+ return (bool)preg_match('/^[\/\.A-Za-z0-9]+$/', $url);
+ }
+
+ /**
+ * Discover the actual data and do some naive caching to ensure that the data
+ * is not requested multiple times.
+ *
+ * If no valid discovery data is found the ownCloud defaults are returned.
+ *
+ * @param string $remote
+ * @return array
+ */
+ private function discover($remote) {
+ // Check if something is in the cache
+ if($cacheData = $this->cache->get($remote)) {
+ return json_decode($cacheData, true);
+ }
+
+ // Default response body
+ $discoveredServices = [
+ 'webdav' => '/public.php/webdav',
+ 'share' => '/ocs/v1.php/cloud/shares',
+ ];
+
+ // Read the data from the response body
+ try {
+ $response = $this->client->get($remote . '/ocs-provider/');
+ if($response->getStatusCode() === 200) {
+ $decodedService = json_decode($response->getBody(), true);
+ if(is_array($decodedService)) {
+ $endpoints = [
+ 'webdav',
+ 'share',
+ ];
+
+ foreach($endpoints as $endpoint) {
+ if(isset($decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint])) {
+ $endpointUrl = (string)$decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint];
+ if($this->isSafeUrl($endpointUrl)) {
+ $discoveredServices[$endpoint] = $endpointUrl;
+ }
+ }
+ }
+ }
+ }
+ } catch (ClientException $e) {
+ } catch (ConnectException $e) {
+ }
+
+ // Write into cache
+ $this->cache->set($remote, json_encode($discoveredServices));
+ return $discoveredServices;
+ }
+
+ /**
+ * Return the public WebDAV endpoint used by the specified remote
+ *
+ * @param string $host
+ * @return string
+ */
+ public function getWebDavEndpoint($host) {
+ return $this->discover($host)['webdav'];
+ }
+
+ /**
+ * Return the sharing endpoint used by the specified remote
+ *
+ * @param string $host
+ * @return string
+ */
+ public function getShareEndpoint($host) {
+ return $this->discover($host)['share'];
+ }
+}
diff --git a/apps/federatedfilesharing/lib/notifications.php b/apps/federatedfilesharing/lib/notifications.php
index d778ac87828..4ec21e81cc7 100644
--- a/apps/federatedfilesharing/lib/notifications.php
+++ b/apps/federatedfilesharing/lib/notifications.php
@@ -1,6 +1,7 @@
<?php
/**
* @author Björn Schießle <schiessle@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
@@ -22,32 +23,31 @@
namespace OCA\FederatedFileSharing;
-
use OCP\Http\Client\IClientService;
class Notifications {
-
- const BASE_PATH_TO_SHARE_API = '/ocs/v1.php/cloud/shares';
const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
/** @var AddressHandler */
private $addressHandler;
-
/** @var IClientService */
private $httpClientService;
+ /** @var DiscoveryManager */
+ private $discoveryManager;
/**
- * Notifications constructor.
- *
* @param AddressHandler $addressHandler
* @param IClientService $httpClientService
+ * @param DiscoveryManager $discoveryManager
*/
public function __construct(
AddressHandler $addressHandler,
- IClientService $httpClientService
+ IClientService $httpClientService,
+ DiscoveryManager $discoveryManager
) {
$this->addressHandler = $addressHandler;
$this->httpClientService = $httpClientService;
+ $this->discoveryManager = $discoveryManager;
}
/**
@@ -65,7 +65,7 @@ class Notifications {
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
if ($user && $remote) {
- $url = $remote . self::BASE_PATH_TO_SHARE_API . '?format=' . self::RESPONSE_FORMAT;
+ $url = $remote;
$local = $this->addressHandler->generateRemoteURL();
$fields = array(
@@ -78,10 +78,10 @@ class Notifications {
);
$url = $this->addressHandler->removeProtocolFromUrl($url);
- $result = $this->tryHttpPost($url, $fields);
+ $result = $this->tryHttpPostToShareEndpoint($url, '', $fields);
$status = json_decode($result['result'], true);
- if ($result['success'] && $status['ocs']['meta']['statuscode'] === 100) {
+ if ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)) {
\OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
return true;
}
@@ -100,23 +100,24 @@ class Notifications {
* @return bool
*/
public function sendRemoteUnShare($remote, $id, $token) {
- $url = rtrim($remote, '/') . self::BASE_PATH_TO_SHARE_API . '/' . $id . '/unshare?format=' . self::RESPONSE_FORMAT;
+ $url = rtrim($remote, '/');
$fields = array('token' => $token, 'format' => 'json');
$url = $this->addressHandler->removeProtocolFromUrl($url);
- $result = $this->tryHttpPost($url, $fields);
+ $result = $this->tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
$status = json_decode($result['result'], true);
- return ($result['success'] && $status['ocs']['meta']['statuscode'] === 100);
+ return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
}
/**
* try http post first with https and then with http as a fallback
*
- * @param string $url
+ * @param string $remoteDomain
+ * @param string $urlSuffix
* @param array $fields post parameters
* @return array
*/
- private function tryHttpPost($url, array $fields) {
+ private function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
$client = $this->httpClientService->newClient();
$protocol = 'https://';
$result = [
@@ -124,9 +125,11 @@ class Notifications {
'result' => '',
];
$try = 0;
+
while ($result['success'] === false && $try < 2) {
+ $endpoint = $this->discoveryManager->getShareEndpoint($protocol . $remoteDomain);
try {
- $response = $client->post($protocol . $url, [
+ $response = $client->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
'body' => $fields
]);
$result['result'] = $response->getBody();
@@ -140,5 +143,4 @@ class Notifications {
return $result;
}
-
}
diff --git a/apps/federatedfilesharing/tests/DiscoveryManagerTest.php b/apps/federatedfilesharing/tests/DiscoveryManagerTest.php
new file mode 100644
index 00000000000..9ae62b1ae4d
--- /dev/null
+++ b/apps/federatedfilesharing/tests/DiscoveryManagerTest.php
@@ -0,0 +1,194 @@
+<?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\FederatedFileSharing\Tests;
+
+use OCA\FederatedFileSharing\DiscoveryManager;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use Test\TestCase;
+
+class DiscoveryManagerTest extends TestCase {
+ /** @var ICache */
+ private $cache;
+ /** @var IClient */
+ private $client;
+ /** @var DiscoveryManager */
+ private $discoveryManager;
+
+ public function setUp() {
+ parent::setUp();
+ $this->cache = $this->getMock('\OCP\ICache');
+ /** @var ICacheFactory $cacheFactory */
+ $cacheFactory = $this->getMockBuilder('\OCP\ICacheFactory')
+ ->disableOriginalConstructor()->getMock();
+ $cacheFactory
+ ->expects($this->once())
+ ->method('create')
+ ->with('ocs-discovery')
+ ->willReturn($this->cache);
+
+ $this->client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ /** @var IClientService $clientService */
+ $clientService = $this->getMockBuilder('\OCP\Http\Client\IClientService')
+ ->disableOriginalConstructor()->getMock();
+ $clientService
+ ->expects($this->once())
+ ->method('newClient')
+ ->willReturn($this->client);
+
+ $this->discoveryManager = new DiscoveryManager(
+ $cacheFactory,
+ $clientService
+ );
+ }
+
+ public function testWithMalformedFormattedEndpointCached() {
+ $response = $this->getMock('\OCP\Http\Client\IResponse');
+ $response
+ ->expects($this->once())
+ ->method('getStatusCode')
+ ->willReturn(200);
+ $response
+ ->expects($this->once())
+ ->method('getBody')
+ ->willReturn('CertainlyNotJson');
+ $this->client
+ ->expects($this->once())
+ ->method('get')
+ ->with('https://myhost.com/ocs-provider/', [])
+ ->willReturn($response);
+ $this->cache
+ ->expects($this->at(0))
+ ->method('get')
+ ->with('https://myhost.com')
+ ->willReturn(null);
+ $this->cache
+ ->expects($this->at(1))
+ ->method('set')
+ ->with('https://myhost.com', '{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
+ $this->cache
+ ->expects($this->at(2))
+ ->method('get')
+ ->with('https://myhost.com')
+ ->willReturn('{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
+
+ $this->assertSame('/public.php/webdav', $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
+ $this->assertSame('/ocs/v1.php/cloud/shares', $this->discoveryManager->getShareEndpoint('https://myhost.com'));
+ }
+
+ public function testGetWebDavEndpointWithValidFormattedEndpointAndNotCached() {
+ $response = $this->getMock('\OCP\Http\Client\IResponse');
+ $response
+ ->expects($this->once())
+ ->method('getStatusCode')
+ ->willReturn(200);
+ $response
+ ->expects($this->once())
+ ->method('getBody')
+ ->willReturn('{"version":2,"services":{"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cloud\/shares","webdav":"\/public.php\/MyCustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}}');
+ $this->client
+ ->expects($this->once())
+ ->method('get')
+ ->with('https://myhost.com/ocs-provider/', [])
+ ->willReturn($response);
+
+ $expectedResult = '/public.php/MyCustomEndpoint/';
+ $this->assertSame($expectedResult, $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
+ }
+
+ public function testGetWebDavEndpointWithValidFormattedEndpointWithoutDataAndNotCached() {
+ $response = $this->getMock('\OCP\Http\Client\IResponse');
+ $response
+ ->expects($this->once())
+ ->method('getStatusCode')
+ ->willReturn(200);
+ $response
+ ->expects($this->once())
+ ->method('getBody')
+ ->willReturn('{"version":2,"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cloud\/shares","webdav":"\/public.php\/MyCustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}');
+ $this->client
+ ->expects($this->once())
+ ->method('get')
+ ->with('https://myhost.com/ocs-provider/', [])
+ ->willReturn($response);
+
+ $expectedResult = '/public.php/webdav';
+ $this->assertSame($expectedResult, $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
+ }
+
+ public function testGetShareEndpointWithValidFormattedEndpointAndNotCached() {
+ $response = $this->getMock('\OCP\Http\Client\IResponse');
+ $response
+ ->expects($this->once())
+ ->method('getStatusCode')
+ ->willReturn(200);
+ $response
+ ->expects($this->once())
+ ->method('getBody')
+ ->willReturn('{"version":2,"services":{"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cloud\/MyCustomShareEndpoint","webdav":"\/public.php\/MyCustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}}');
+ $this->client
+ ->expects($this->once())
+ ->method('get')
+ ->with('https://myhost.com/ocs-provider/', [])
+ ->willReturn($response);
+
+ $expectedResult = '/ocs/v2.php/cloud/MyCustomShareEndpoint';
+ $this->assertSame($expectedResult, $this->discoveryManager->getShareEndpoint('https://myhost.com'));
+ }
+
+ public function testWithMaliciousEndpointCached() {
+ $response = $this->getMock('\OCP\Http\Client\IResponse');
+ $response
+ ->expects($this->once())
+ ->method('getStatusCode')
+ ->willReturn(200);
+ $response
+ ->expects($this->once())
+ ->method('getBody')
+ ->willReturn('{"version":2,"services":{"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cl@oud\/MyCustomShareEndpoint","webdav":"\/public.php\/MyC:ustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}}');
+ $this->client
+ ->expects($this->once())
+ ->method('get')
+ ->with('https://myhost.com/ocs-provider/', [])
+ ->willReturn($response);
+ $this->cache
+ ->expects($this->at(0))
+ ->method('get')
+ ->with('https://myhost.com')
+ ->willReturn(null);
+ $this->cache
+ ->expects($this->at(1))
+ ->method('set')
+ ->with('https://myhost.com', '{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
+ $this->cache
+ ->expects($this->at(2))
+ ->method('get')
+ ->with('https://myhost.com')
+ ->willReturn('{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
+
+ $this->assertSame('/public.php/webdav', $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
+ $this->assertSame('/ocs/v1.php/cloud/shares', $this->discoveryManager->getShareEndpoint('https://myhost.com'));
+ }
+}
diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php
index 1efe4356b4c..2e963d55491 100644
--- a/apps/files_sharing/ajax/external.php
+++ b/apps/files_sharing/ajax/external.php
@@ -57,7 +57,10 @@ if (\OC\Share\Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $cur
exit();
}
-
+$discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+);
$externalManager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
diff --git a/apps/files_sharing/api/remote.php b/apps/files_sharing/api/remote.php
index 8b47955b51e..1b5eb28aa86 100644
--- a/apps/files_sharing/api/remote.php
+++ b/apps/files_sharing/api/remote.php
@@ -24,6 +24,7 @@
namespace OCA\Files_Sharing\API;
use OC\Files\Filesystem;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\Files_Sharing\External\Manager;
class Remote {
@@ -35,12 +36,17 @@ class Remote {
* @return \OC_OCS_Result
*/
public static function getOpenShares($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
\OC_User::getUser()
);
@@ -54,12 +60,17 @@ class Remote {
* @return \OC_OCS_Result
*/
public static function acceptShare($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
\OC_User::getUser()
);
@@ -80,12 +91,17 @@ class Remote {
* @return \OC_OCS_Result
*/
public static function declineShare($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
\OC_User::getUser()
);
@@ -123,12 +139,17 @@ class Remote {
* @return \OC_OCS_Result
*/
public static function getShares($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
\OC_User::getUser()
);
@@ -146,12 +167,17 @@ class Remote {
* @return \OC_OCS_Result
*/
public static function getShare($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
\OC_User::getUser()
);
@@ -172,12 +198,17 @@ class Remote {
* @return \OC_OCS_Result
*/
public static function unshare($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
\OC_User::getUser()
);
diff --git a/apps/files_sharing/api/server2server.php b/apps/files_sharing/api/server2server.php
index f04ddc81b84..6da95ed6549 100644
--- a/apps/files_sharing/api/server2server.php
+++ b/apps/files_sharing/api/server2server.php
@@ -25,6 +25,7 @@
namespace OCA\Files_Sharing\API;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\Files_Sharing\Activity;
use OCP\Files\NotFoundException;
@@ -70,12 +71,17 @@ class Server2Server {
\OC_Util::setupFS($shareWith);
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$externalManager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
$shareWith
);
diff --git a/apps/files_sharing/appinfo/application.php b/apps/files_sharing/appinfo/application.php
index e4a2262fece..64c7517456d 100644
--- a/apps/files_sharing/appinfo/application.php
+++ b/apps/files_sharing/appinfo/application.php
@@ -24,6 +24,7 @@
namespace OCA\Files_Sharing\AppInfo;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\Files_Sharing\MountProvider;
use OCP\AppFramework\App;
use OC\AppFramework\Utility\SimpleContainer;
@@ -76,12 +77,17 @@ class Application extends App {
$container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) {
$user = $server->getUserSession()->getUser();
$uid = $user ? $user->getUID() : null;
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
return new \OCA\Files_Sharing\External\Manager(
$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
$server->getHTTPHelper(),
$server->getNotificationManager(),
+ $discoveryManager,
$uid
);
});
diff --git a/apps/files_sharing/lib/external/manager.php b/apps/files_sharing/lib/external/manager.php
index 84de1da69f6..ec487449625 100644
--- a/apps/files_sharing/lib/external/manager.php
+++ b/apps/files_sharing/lib/external/manager.php
@@ -27,6 +27,7 @@
namespace OCA\Files_Sharing\External;
use OC\Files\Filesystem;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCP\Files;
use OCP\Notification\IManager;
@@ -62,6 +63,8 @@ class Manager {
* @var IManager
*/
private $notificationManager;
+ /** @var DiscoveryManager */
+ private $discoveryManager;
/**
* @param \OCP\IDBConnection $connection
@@ -69,16 +72,23 @@ class Manager {
* @param \OCP\Files\Storage\IStorageFactory $storageLoader
* @param \OC\HTTPHelper $httpHelper
* @param IManager $notificationManager
+ * @param DiscoveryManager $discoveryManager
* @param string $uid
*/
- public function __construct(\OCP\IDBConnection $connection, \OC\Files\Mount\Manager $mountManager,
- \OCP\Files\Storage\IStorageFactory $storageLoader, \OC\HTTPHelper $httpHelper, IManager $notificationManager, $uid) {
+ public function __construct(\OCP\IDBConnection $connection,
+ \OC\Files\Mount\Manager $mountManager,
+ \OCP\Files\Storage\IStorageFactory $storageLoader,
+ \OC\HTTPHelper $httpHelper,
+ IManager $notificationManager,
+ DiscoveryManager $discoveryManager,
+ $uid) {
$this->connection = $connection;
$this->mountManager = $mountManager;
$this->storageLoader = $storageLoader;
$this->httpHelper = $httpHelper;
$this->uid = $uid;
$this->notificationManager = $notificationManager;
+ $this->discoveryManager = $discoveryManager;
}
/**
@@ -246,13 +256,13 @@ class Manager {
*/
private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
- $url = rtrim($remote, '/') . \OCP\Share::BASE_PATH_TO_SHARE_API . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
+ $url = rtrim($remote, '/') . $this->discoveryManager->getShareEndpoint($remote) . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
$fields = array('token' => $token);
$result = $this->httpHelper->post($url, $fields);
$status = json_decode($result['result'], true);
- return ($result['success'] && $status['ocs']['meta']['statuscode'] === 100);
+ return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
}
/**
diff --git a/apps/files_sharing/lib/external/storage.php b/apps/files_sharing/lib/external/storage.php
index ba7fba654a9..5e4b2df7c7f 100644
--- a/apps/files_sharing/lib/external/storage.php
+++ b/apps/files_sharing/lib/external/storage.php
@@ -27,6 +27,7 @@ namespace OCA\Files_Sharing\External;
use OC\Files\Storage\DAV;
use OC\ForbiddenException;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\Files_Sharing\ISharedStorage;
use OCP\Files\NotFoundException;
use OCP\Files\StorageInvalidException;
@@ -66,6 +67,11 @@ class Storage extends DAV implements ISharedStorage {
private $manager;
public function __construct($options) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
+
$this->manager = $options['manager'];
$this->certificateManager = $options['certificateManager'];
$this->remote = $options['remote'];
@@ -78,7 +84,7 @@ class Storage extends DAV implements ISharedStorage {
$root = '';
}
$secure = $protocol === 'https';
- $root = rtrim($root, '/') . '/public.php/webdav';
+ $root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->remote);
$this->mountPoint = $options['mountpoint'];
$this->token = $options['token'];
parent::__construct(array(
diff --git a/apps/files_sharing/lib/hooks.php b/apps/files_sharing/lib/hooks.php
index 166905b9aa4..e3f24d02268 100644
--- a/apps/files_sharing/lib/hooks.php
+++ b/apps/files_sharing/lib/hooks.php
@@ -25,16 +25,22 @@
namespace OCA\Files_Sharing;
use OC\Files\Filesystem;
+use OCA\FederatedFileSharing\DiscoveryManager;
class Hooks {
public static function deleteUser($params) {
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$manager = new External\Manager(
\OC::$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
$params['uid']);
$manager->removeUserShares($params['uid']);
diff --git a/apps/files_sharing/tests/external/managertest.php b/apps/files_sharing/tests/external/managertest.php
index f73fedaf05c..2836a3dc024 100644
--- a/apps/files_sharing/tests/external/managertest.php
+++ b/apps/files_sharing/tests/external/managertest.php
@@ -24,6 +24,7 @@
namespace OCA\Files_Sharing\Tests\External;
use OC\Files\Storage\StorageFactory;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\Files_Sharing\External\Manager;
use OCA\Files_Sharing\External\MountProvider;
use OCA\Files_Sharing\Tests\TestCase;
@@ -64,6 +65,10 @@ class ManagerTest extends TestCase {
$this->user = \OC::$server->getUserManager()->get($this->uid);
$this->mountManager = new \OC\Files\Mount\Manager();
$this->httpHelper = $httpHelper = $this->getMockBuilder('\OC\HTTPHelper')->disableOriginalConstructor()->getMock();
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
/** @var \OC\HTTPHelper $httpHelper */
$this->manager = new Manager(
\OC::$server->getDatabaseConnection(),
@@ -71,6 +76,7 @@ class ManagerTest extends TestCase {
new StorageFactory(),
$httpHelper,
\OC::$server->getNotificationManager(),
+ $discoveryManager,
$this->uid
);
$this->mountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() {
diff --git a/apps/files_sharing/tests/server2server.php b/apps/files_sharing/tests/server2server.php
index a282f92ecb9..298f1008f71 100644
--- a/apps/files_sharing/tests/server2server.php
+++ b/apps/files_sharing/tests/server2server.php
@@ -153,14 +153,19 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase {
function testDeleteUser($toDelete, $expected, $remainingUsers) {
$this->createDummyS2SShares();
+ $discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
$manager = new OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
+ $discoveryManager,
$toDelete
- );
+ );
$manager->removeUserShares($toDelete);
diff --git a/lib/private/share/constants.php b/lib/private/share/constants.php
index e2b87d72476..e60eb98832b 100644
--- a/lib/private/share/constants.php
+++ b/lib/private/share/constants.php
@@ -40,8 +40,6 @@ class Constants {
const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility
- const BASE_PATH_TO_SHARE_API = '/ocs/v1.php/cloud/shares';
-
protected static $shareTypeUserAndGroups = -1;
protected static $shareTypeGroupUserUnique = 2;
protected static $backends = array();
diff --git a/lib/private/share/share.php b/lib/private/share/share.php
index 149dd082bbc..4453e3758ba 100644
--- a/lib/private/share/share.php
+++ b/lib/private/share/share.php
@@ -38,6 +38,7 @@
namespace OC\Share;
use OC\Files\Filesystem;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IUserSession;
use OCP\IDBConnection;
@@ -2620,19 +2621,25 @@ class Share extends Constants {
/**
* try http post first with https and then with http as a fallback
*
- * @param string $url
+ * @param string $remoteDomain
+ * @param string $urlSuffix
* @param array $fields post parameters
* @return array
*/
- private static function tryHttpPost($url, $fields) {
+ private static function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
$protocol = 'https://';
$result = [
'success' => false,
'result' => '',
];
$try = 0;
+ $discoveryManager = new DiscoveryManager(
+ \OC::$server->getMemCacheFactory(),
+ \OC::$server->getHTTPClientService()
+ );
while ($result['success'] === false && $try < 2) {
- $result = \OC::$server->getHTTPHelper()->post($protocol . $url, $fields);
+ $endpoint = $discoveryManager->getShareEndpoint($protocol . $remoteDomain);
+ $result = \OC::$server->getHTTPHelper()->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, $fields);
$try++;
$protocol = 'http://';
}
@@ -2655,7 +2662,7 @@ class Share extends Constants {
list($user, $remote) = Helper::splitUserRemote($shareWith);
if ($user && $remote) {
- $url = $remote . self::BASE_PATH_TO_SHARE_API . '?format=' . self::RESPONSE_FORMAT;
+ $url = $remote;
$local = \OC::$server->getURLGenerator()->getAbsoluteURL('/');
@@ -2669,10 +2676,10 @@ class Share extends Constants {
);
$url = self::removeProtocolFromUrl($url);
- $result = self::tryHttpPost($url, $fields);
+ $result = self::tryHttpPostToShareEndpoint($url, '', $fields);
$status = json_decode($result['result'], true);
- if ($result['success'] && $status['ocs']['meta']['statuscode'] === 100) {
+ if ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)) {
\OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
return true;
}
@@ -2691,13 +2698,13 @@ class Share extends Constants {
* @return bool
*/
private static function sendRemoteUnshare($remote, $id, $token) {
- $url = rtrim($remote, '/') . self::BASE_PATH_TO_SHARE_API . '/' . $id . '/unshare?format=' . self::RESPONSE_FORMAT;
+ $url = rtrim($remote, '/');
$fields = array('token' => $token, 'format' => 'json');
$url = self::removeProtocolFromUrl($url);
- $result = self::tryHttpPost($url, $fields);
+ $result = self::tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
$status = json_decode($result['result'], true);
- return ($result['success'] && $status['ocs']['meta']['statuscode'] === 100);
+ return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
}
/**
diff --git a/lib/private/share20/providerfactory.php b/lib/private/share20/providerfactory.php
index bb440d2e01f..c2980b22515 100644
--- a/lib/private/share20/providerfactory.php
+++ b/lib/private/share20/providerfactory.php
@@ -21,6 +21,7 @@
namespace OC\Share20;
use OCA\FederatedFileSharing\AddressHandler;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\FederatedFileSharing\Notifications;
use OCA\FederatedFileSharing\TokenHandler;
@@ -91,9 +92,14 @@ class ProviderFactory implements IProviderFactory {
$this->serverContainer->getURLGenerator(),
$l
);
+ $discoveryManager = new DiscoveryManager(
+ $this->serverContainer->getMemCacheFactory(),
+ $this->serverContainer->getHTTPClientService()
+ );
$notifications = new Notifications(
$addressHandler,
- $this->serverContainer->getHTTPClientService()
+ $this->serverContainer->getHTTPClientService(),
+ $discoveryManager
);
$tokenHandler = new TokenHandler(
$this->serverContainer->getSecureRandom()