summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/lib/CardDAV/SyncService.php31
-rw-r--r--apps/dav/tests/unit/CardDAV/SyncServiceTest.php8
-rw-r--r--apps/federatedfilesharing/lib/AppInfo/Application.php11
-rw-r--r--apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php9
-rw-r--r--apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php6
-rw-r--r--apps/federatedfilesharing/lib/Controller/RequestHandlerController.php20
-rw-r--r--apps/federatedfilesharing/lib/DiscoveryManager.php143
-rw-r--r--apps/federatedfilesharing/lib/Notifications.php14
-rw-r--r--apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php6
-rw-r--r--apps/federatedfilesharing/tests/DiscoveryManagerTest.php217
-rw-r--r--apps/federatedfilesharing/tests/NotificationsTest.php13
-rw-r--r--apps/federation/appinfo/routes.php4
-rw-r--r--apps/federation/lib/AppInfo/Application.php3
-rw-r--r--apps/federation/lib/BackgroundJob/GetSharedSecret.php21
-rw-r--r--apps/federation/lib/BackgroundJob/RequestSharedSecret.php21
-rw-r--r--apps/federation/lib/Controller/OCSAuthAPIController.php31
-rw-r--r--apps/federation/lib/SyncFederationAddressBooks.php22
-rw-r--r--apps/federation/tests/BackgroundJob/GetSharedSecretTest.php13
-rw-r--r--apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php13
-rw-r--r--apps/federation/tests/SyncFederationAddressbooksTest.php20
-rw-r--r--apps/files_sharing/lib/AppInfo/Application.php6
-rw-r--r--apps/files_sharing/lib/External/Manager.php35
-rw-r--r--apps/files_sharing/lib/External/Storage.php16
-rw-r--r--apps/files_sharing/lib/Hooks.php6
-rw-r--r--apps/files_sharing/tests/External/ManagerTest.php15
-rw-r--r--lib/composer/composer/autoload_classmap.php2
-rw-r--r--lib/composer/composer/autoload_static.php2
-rw-r--r--lib/private/OCS/DiscoveryService.php125
-rw-r--r--lib/private/Server.php5
-rw-r--r--lib/private/Share/Share.php8
-rw-r--r--lib/private/Share20/ProviderFactory.php6
-rw-r--r--lib/public/OCS/IDiscoveryService.php48
-rw-r--r--tests/lib/OCS/DiscoveryServiceTest.php99
-rw-r--r--tests/lib/Share/ShareTest.php12
34 files changed, 502 insertions, 509 deletions
diff --git a/apps/dav/lib/CardDAV/SyncService.php b/apps/dav/lib/CardDAV/SyncService.php
index 477e912a797..b6f57753431 100644
--- a/apps/dav/lib/CardDAV/SyncService.php
+++ b/apps/dav/lib/CardDAV/SyncService.php
@@ -75,6 +75,7 @@ class SyncService {
/**
* @param string $url
* @param string $userName
+ * @param string $addressBookUrl
* @param string $sharedSecret
* @param string $syncToken
* @param int $targetBookId
@@ -83,14 +84,14 @@ class SyncService {
* @return string
* @throws \Exception
*/
- public function syncRemoteAddressBook($url, $userName, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) {
+ public function syncRemoteAddressBook($url, $userName, $addressBookUrl, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) {
// 1. create addressbook
$book = $this->ensureSystemAddressBookExists($targetPrincipal, $targetBookId, $targetProperties);
$addressBookId = $book['id'];
// 2. query changes
try {
- $response = $this->requestSyncReport($url, $userName, $sharedSecret, $syncToken);
+ $response = $this->requestSyncReport($url, $userName, $addressBookUrl, $sharedSecret, $syncToken);
} catch (ClientHttpException $ex) {
if ($ex->getCode() === Http::STATUS_UNAUTHORIZED) {
// remote server revoked access to the address book, remove it
@@ -105,7 +106,7 @@ class SyncService {
foreach ($response['response'] as $resource => $status) {
$cardUri = basename($resource);
if (isset($status[200])) {
- $vCard = $this->download($url, $sharedSecret, $resource);
+ $vCard = $this->download($url, $userName, $sharedSecret, $resource);
$existingCard = $this->backend->getCard($addressBookId, $cardUri);
if ($existingCard === false) {
$this->backend->createCard($addressBookId, $cardUri, $vCard['body']);
@@ -162,6 +163,7 @@ class SyncService {
/**
* @param string $url
* @param string $userName
+ * @param string $addressBookUrl
* @param string $sharedSecret
* @return Client
*/
@@ -185,31 +187,32 @@ class SyncService {
/**
* @param string $url
* @param string $userName
+ * @param string $addressBookUrl
* @param string $sharedSecret
* @param string $syncToken
* @return array
*/
- protected function requestSyncReport($url, $userName, $sharedSecret, $syncToken) {
- $client = $this->getClient($url, $userName, $sharedSecret);
+ protected function requestSyncReport($url, $userName, $addressBookUrl, $sharedSecret, $syncToken) {
+ $client = $this->getClient($url, $userName, $sharedSecret);
- $addressBookUrl = "remote.php/dav/addressbooks/system/system/system";
- $body = $this->buildSyncCollectionRequestBody($syncToken);
+ $body = $this->buildSyncCollectionRequestBody($syncToken);
- $response = $client->request('REPORT', $addressBookUrl, $body, [
- 'Content-Type' => 'application/xml'
- ]);
+ $response = $client->request('REPORT', $addressBookUrl, $body, [
+ 'Content-Type' => 'application/xml'
+ ]);
- return $this->parseMultiStatus($response['body']);
- }
+ return $this->parseMultiStatus($response['body']);
+ }
/**
* @param string $url
+ * @param string $userName
* @param string $sharedSecret
* @param string $resourcePath
* @return array
*/
- protected function download($url, $sharedSecret, $resourcePath) {
- $client = $this->getClient($url, 'system', $sharedSecret);
+ protected function download($url, $userName, $sharedSecret, $resourcePath) {
+ $client = $this->getClient($url, $userName, $sharedSecret);
return $client->request('GET', $resourcePath);
}
diff --git a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
index c06e4857743..32f8a2424b1 100644
--- a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
@@ -37,7 +37,7 @@ class SyncServiceTest extends TestCase {
$backend = $this->getBackendMock(0, 0, 0);
$ss = $this->getSyncServiceMock($backend, []);
- $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
+ $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
$this->assertEquals('sync-token-1', $return);
}
@@ -46,7 +46,7 @@ class SyncServiceTest extends TestCase {
$backend->method('getCard')->willReturn(false);
$ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
- $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
+ $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
$this->assertEquals('sync-token-1', $return);
}
@@ -55,7 +55,7 @@ class SyncServiceTest extends TestCase {
$backend->method('getCard')->willReturn(true);
$ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
- $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
+ $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
$this->assertEquals('sync-token-1', $return);
}
@@ -63,7 +63,7 @@ class SyncServiceTest extends TestCase {
$backend = $this->getBackendMock(0, 0, 1);
$ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]);
- $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
+ $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
$this->assertEquals('sync-token-1', $return);
}
diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php
index 3e97edeada0..9d8464e37d5 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -51,10 +51,7 @@ class Application extends App {
$notification = new Notifications(
$addressHandler,
$server->getHTTPClientService(),
- new \OCA\FederatedFileSharing\DiscoveryManager(
- $server->getMemCacheFactory(),
- $server->getHTTPClientService()
- ),
+ $server->query(\OCP\OCS\IDiscoveryService::class),
\OC::$server->getJobList()
);
return new RequestHandlerController(
@@ -99,14 +96,10 @@ class Application extends App {
\OC::$server->getL10N('federatedfilesharing'),
\OC::$server->getCloudIdManager()
);
- $discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager(
- \OC::$server->getMemCacheFactory(),
- \OC::$server->getHTTPClientService()
- );
$notifications = new \OCA\FederatedFileSharing\Notifications(
$addressHandler,
\OC::$server->getHTTPClientService(),
- $discoveryManager,
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
\OC::$server->getJobList()
);
$tokenHandler = new \OCA\FederatedFileSharing\TokenHandler(
diff --git a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
index 2356c569d87..821647e5e39 100644
--- a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
+++ b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
@@ -27,7 +27,6 @@ namespace OCA\FederatedFileSharing\BackgroundJob;
use OC\BackgroundJob\Job;
use OC\BackgroundJob\JobList;
use OCA\FederatedFileSharing\AddressHandler;
-use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\FederatedFileSharing\Notifications;
use OCP\BackgroundJob\IJobList;
use OCP\ILogger;
@@ -68,14 +67,10 @@ class RetryJob extends Job {
\OC::$server->getL10N('federatedfilesharing'),
\OC::$server->getCloudIdManager()
);
- $discoveryManager = new DiscoveryManager(
- \OC::$server->getMemCacheFactory(),
- \OC::$server->getHTTPClientService()
- );
$this->notifications = new Notifications(
$addressHandler,
\OC::$server->getHTTPClientService(),
- $discoveryManager,
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
\OC::$server->getJobList()
);
}
@@ -108,7 +103,7 @@ class RetryJob extends Job {
$try = (int)$argument['try'] + 1;
$result = $this->notifications->sendUpdateToRemote($remote, $remoteId, $token, $action, $data, $try);
-
+
if ($result === true || $try > $this->maxTry) {
$this->retainJob = false;
}
diff --git a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php
index dd2e88d2dae..d7e466d1a64 100644
--- a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php
+++ b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php
@@ -248,17 +248,13 @@ class MountPublicLinkController extends Controller {
if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
}
- $discoveryManager = new DiscoveryManager(
- \OC::$server->getMemCacheFactory(),
- \OC::$server->getHTTPClientService()
- );
$externalManager = new Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPClientService(),
\OC::$server->getNotificationManager(),
- $discoveryManager,
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
\OC::$server->getUserSession()->getUser()->getUID()
);
diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
index a41481afd2a..2b643810fb4 100644
--- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
+++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
@@ -152,19 +152,15 @@ class RequestHandlerController extends OCSController {
\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->getHTTPClientService(),
- \OC::$server->getNotificationManager(),
- $discoveryManager,
- $shareWith
- );
+ \OC::$server->getDatabaseConnection(),
+ \OC\Files\Filesystem::getMountManager(),
+ \OC\Files\Filesystem::getLoader(),
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getNotificationManager(),
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
+ $shareWith
+ );
try {
$externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
diff --git a/apps/federatedfilesharing/lib/DiscoveryManager.php b/apps/federatedfilesharing/lib/DiscoveryManager.php
deleted file mode 100644
index 8c8c72dbd66..00000000000
--- a/apps/federatedfilesharing/lib/DiscoveryManager.php
+++ /dev/null
@@ -1,143 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @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 Nextcloud 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/', [
- 'timeout' => 10,
- 'connect_timeout' => 10,
- ]);
- 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) {
- // Don't throw any exception since exceptions are handled before
- } catch (ConnectException $e) {
- // Don't throw any exception since exceptions are handled before
- }
-
- // 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 8110b4915da..5abac711985 100644
--- a/apps/federatedfilesharing/lib/Notifications.php
+++ b/apps/federatedfilesharing/lib/Notifications.php
@@ -30,6 +30,7 @@ namespace OCA\FederatedFileSharing;
use OCP\AppFramework\Http;
use OCP\BackgroundJob\IJobList;
use OCP\Http\Client\IClientService;
+use OCP\OCS\IDiscoveryService;
class Notifications {
const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
@@ -40,8 +41,8 @@ class Notifications {
/** @var IClientService */
private $httpClientService;
- /** @var DiscoveryManager */
- private $discoveryManager;
+ /** @var IDiscoveryService */
+ private $discoveryService;
/** @var IJobList */
private $jobList;
@@ -49,18 +50,18 @@ class Notifications {
/**
* @param AddressHandler $addressHandler
* @param IClientService $httpClientService
- * @param DiscoveryManager $discoveryManager
+ * @param IDiscoveryService $discoveryService
* @param IJobList $jobList
*/
public function __construct(
AddressHandler $addressHandler,
IClientService $httpClientService,
- DiscoveryManager $discoveryManager,
+ IDiscoveryService $discoveryService,
IJobList $jobList
) {
$this->addressHandler = $addressHandler;
$this->httpClientService = $httpClientService;
- $this->discoveryManager = $discoveryManager;
+ $this->discoveryService = $discoveryService;
$this->jobList = $jobList;
}
@@ -287,7 +288,8 @@ class Notifications {
'result' => '',
];
- $endpoint = $this->discoveryManager->getShareEndpoint($remoteDomain);
+ $federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
+ $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
try {
$response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
'body' => $fields,
diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
index 233395dec9f..512000181c1 100644
--- a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
+++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
@@ -270,17 +270,13 @@ class RequestHandlerControllerTest extends TestCase {
->method('newClient')
->willReturn($client);
- $discoveryManager = new DiscoveryManager(
- \OC::$server->getMemCacheFactory(),
- $httpClientService
- );
$manager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
Filesystem::getMountManager(),
Filesystem::getLoader(),
$httpClientService,
\OC::$server->getNotificationManager(),
- $discoveryManager,
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
$toDelete
);
diff --git a/apps/federatedfilesharing/tests/DiscoveryManagerTest.php b/apps/federatedfilesharing/tests/DiscoveryManagerTest.php
deleted file mode 100644
index 77e24aad54b..00000000000
--- a/apps/federatedfilesharing/tests/DiscoveryManagerTest.php
+++ /dev/null
@@ -1,217 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @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;
-
-class DiscoveryManagerTest extends \Test\TestCase {
- /** @var ICache */
- private $cache;
- /** @var IClient */
- private $client;
- /** @var DiscoveryManager */
- private $discoveryManager;
-
- public function setUp() {
- parent::setUp();
- $this->cache = $this->getMockBuilder('\OCP\ICache')
- ->getMock();
- /** @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->getMockBuilder('\OCP\Http\Client\IResponse')
- ->getMock();
- $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/', [
- 'timeout' => 10,
- 'connect_timeout' => 10,
- ])
- ->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->getMockBuilder('\OCP\Http\Client\IResponse')
- ->getMock();
- $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/', [
- 'timeout' => 10,
- 'connect_timeout' => 10,
- ])
- ->willReturn($response);
-
- $expectedResult = '/public.php/MyCustomEndpoint/';
- $this->assertSame($expectedResult, $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
- }
-
- public function testGetWebDavEndpointWithValidFormattedEndpointWithoutDataAndNotCached() {
- $response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
- ->getMock();
- $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/', [
- 'timeout' => 10,
- 'connect_timeout' => 10,
- ])
- ->willReturn($response);
-
- $expectedResult = '/public.php/webdav';
- $this->assertSame($expectedResult, $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
- }
-
- public function testGetShareEndpointWithValidFormattedEndpointAndNotCached() {
- $response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
- ->getMock();
- $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/', [
- 'timeout' => 10,
- 'connect_timeout' => 10,
- ])
- ->willReturn($response);
-
- $expectedResult = '/ocs/v2.php/cloud/MyCustomShareEndpoint';
- $this->assertSame($expectedResult, $this->discoveryManager->getShareEndpoint('https://myhost.com'));
- }
-
- public function testWithMaliciousEndpointCached() {
- $response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
- ->getMock();
- $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/', [
- 'timeout' => 10,
- 'connect_timeout' => 10,
- ])
- ->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/federatedfilesharing/tests/NotificationsTest.php b/apps/federatedfilesharing/tests/NotificationsTest.php
index a5f5c6bc078..4f70d5f3950 100644
--- a/apps/federatedfilesharing/tests/NotificationsTest.php
+++ b/apps/federatedfilesharing/tests/NotificationsTest.php
@@ -25,10 +25,10 @@ namespace OCA\FederatedFileSharing\Tests;
use OCA\FederatedFileSharing\AddressHandler;
-use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\FederatedFileSharing\Notifications;
use OCP\BackgroundJob\IJobList;
use OCP\Http\Client\IClientService;
+use OCP\OCS\IDiscoveryService;
class NotificationsTest extends \Test\TestCase {
@@ -38,8 +38,8 @@ class NotificationsTest extends \Test\TestCase {
/** @var IClientService | \PHPUnit_Framework_MockObject_MockObject*/
private $httpClientService;
- /** @var DiscoveryManager | \PHPUnit_Framework_MockObject_MockObject */
- private $discoveryManager;
+ /** @var IDiscoveryService | \PHPUnit_Framework_MockObject_MockObject */
+ private $discoveryService;
/** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */
private $jobList;
@@ -48,8 +48,7 @@ class NotificationsTest extends \Test\TestCase {
parent::setUp();
$this->jobList = $this->getMockBuilder('OCP\BackgroundJob\IJobList')->getMock();
- $this->discoveryManager = $this->getMockBuilder('OCA\FederatedFileSharing\DiscoveryManager')
- ->disableOriginalConstructor()->getMock();
+ $this->discoveryService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
$this->httpClientService = $this->getMockBuilder('OCP\Http\Client\IClientService')->getMock();
$this->addressHandler = $this->getMockBuilder('OCA\FederatedFileSharing\AddressHandler')
->disableOriginalConstructor()->getMock();
@@ -67,7 +66,7 @@ class NotificationsTest extends \Test\TestCase {
$instance = new Notifications(
$this->addressHandler,
$this->httpClientService,
- $this->discoveryManager,
+ $this->discoveryService,
$this->jobList
);
} else {
@@ -76,7 +75,7 @@ class NotificationsTest extends \Test\TestCase {
[
$this->addressHandler,
$this->httpClientService,
- $this->discoveryManager,
+ $this->discoveryService,
$this->jobList
]
)->setMethods($mockedMethods)->getMock();
diff --git a/apps/federation/appinfo/routes.php b/apps/federation/appinfo/routes.php
index 4c742dd705c..01c37eab584 100644
--- a/apps/federation/appinfo/routes.php
+++ b/apps/federation/appinfo/routes.php
@@ -45,12 +45,12 @@ $application->registerRoutes(
'ocs' => [
// old endpoints, only used by Nextcloud and ownCloud
[
- 'name' => 'OCSAuthAPI#getSharedSecret',
+ 'name' => 'OCSAuthAPI#getSharedSecretLegacy',
'url' => '/api/v1/shared-secret',
'verb' => 'GET',
],
[
- 'name' => 'OCSAuthAPI#requestSharedSecret',
+ 'name' => 'OCSAuthAPI#requestSharedSecretLegacy',
'url' => '/api/v1/request-shared-secret',
'verb' => 'POST',
],
diff --git a/apps/federation/lib/AppInfo/Application.php b/apps/federation/lib/AppInfo/Application.php
index e5acab52857..3166316b108 100644
--- a/apps/federation/lib/AppInfo/Application.php
+++ b/apps/federation/lib/AppInfo/Application.php
@@ -135,7 +135,8 @@ class Application extends \OCP\AppFramework\App {
public function getSyncService() {
$syncService = \OC::$server->query('CardDAVSyncService');
$dbHandler = $this->getContainer()->query('DbHandler');
- return new SyncFederationAddressBooks($dbHandler, $syncService);
+ $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
+ return new SyncFederationAddressBooks($dbHandler, $syncService, $discoveryService);
}
}
diff --git a/apps/federation/lib/BackgroundJob/GetSharedSecret.php b/apps/federation/lib/BackgroundJob/GetSharedSecret.php
index c0a4b43db64..4a6e720ae2c 100644
--- a/apps/federation/lib/BackgroundJob/GetSharedSecret.php
+++ b/apps/federation/lib/BackgroundJob/GetSharedSecret.php
@@ -37,6 +37,7 @@ use OCP\Http\Client\IClient;
use OCP\Http\Client\IResponse;
use OCP\ILogger;
use OCP\IURLGenerator;
+use OCP\OCS\IDiscoveryService;
/**
* Class GetSharedSecret
@@ -62,13 +63,18 @@ class GetSharedSecret extends Job{
/** @var DbHandler */
private $dbHandler;
+ /** @var IDiscoveryService */
+ private $ocsDiscoveryService;
+
/** @var ILogger */
private $logger;
/** @var bool */
protected $retainJob = false;
- private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json';
+ private $format = '?format=json';
+
+ private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
/**
* RequestSharedSecret constructor.
@@ -79,6 +85,7 @@ class GetSharedSecret extends Job{
* @param TrustedServers $trustedServers
* @param ILogger $logger
* @param DbHandler $dbHandler
+ * @param IDiscoveryService $ocsDiscoveryService
*/
public function __construct(
IClient $httpClient = null,
@@ -86,13 +93,15 @@ class GetSharedSecret extends Job{
IJobList $jobList = null,
TrustedServers $trustedServers = null,
ILogger $logger = null,
- DbHandler $dbHandler = null
+ DbHandler $dbHandler = null,
+ IDiscoveryService $ocsDiscoveryService = null
) {
$this->logger = $logger ? $logger : \OC::$server->getLogger();
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
+ $this->ocsDiscoveryService = $ocsDiscoveryService ? $ocsDiscoveryService : \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
if ($trustedServers) {
$this->trustedServers = $trustedServers;
} else {
@@ -142,10 +151,16 @@ class GetSharedSecret extends Job{
$source = rtrim($source, '/');
$token = $argument['token'];
+ $endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
+ $endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
+
+ // make sure that we have a well formated url
+ $url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
+
$result = null;
try {
$result = $this->httpClient->get(
- $target . $this->endPoint,
+ $url,
[
'query' =>
[
diff --git a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php
index 352995572c9..60b22cd6283 100644
--- a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php
+++ b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php
@@ -37,6 +37,7 @@ use OCP\BackgroundJob\IJobList;
use OCP\Http\Client\IClient;
use OCP\ILogger;
use OCP\IURLGenerator;
+use OCP\OCS\IDiscoveryService;
/**
* Class RequestSharedSecret
@@ -62,7 +63,8 @@ class RequestSharedSecret extends Job {
/** @var TrustedServers */
private $trustedServers;
- private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json';
+ /** @var IDiscoveryService */
+ private $ocsDiscoveryService;
/** @var ILogger */
private $logger;
@@ -70,6 +72,10 @@ class RequestSharedSecret extends Job {
/** @var bool */
protected $retainJob = false;
+ private $format = '?format=json';
+
+ private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret';
+
/**
* RequestSharedSecret constructor.
*
@@ -78,19 +84,22 @@ class RequestSharedSecret extends Job {
* @param IJobList $jobList
* @param TrustedServers $trustedServers
* @param DbHandler $dbHandler
+ * @param IDiscoveryService $ocsDiscoveryService
*/
public function __construct(
IClient $httpClient = null,
IURLGenerator $urlGenerator = null,
IJobList $jobList = null,
TrustedServers $trustedServers = null,
- DbHandler $dbHandler = null
+ DbHandler $dbHandler = null,
+ IDiscoveryService $ocsDiscoveryService = null
) {
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
$this->logger = \OC::$server->getLogger();
+ $this->ocsDiscoveryService = $ocsDiscoveryService ? $ocsDiscoveryService : \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
if ($trustedServers) {
$this->trustedServers = $trustedServers;
} else {
@@ -142,9 +151,15 @@ class RequestSharedSecret extends Job {
$source = rtrim($source, '/');
$token = $argument['token'];
+ $endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
+ $endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
+
+ // make sure that we have a well formated url
+ $url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
+
try {
$result = $this->httpClient->post(
- $target . $this->endPoint,
+ $url,
[
'body' => [
'url' => $source,
diff --git a/apps/federation/lib/Controller/OCSAuthAPIController.php b/apps/federation/lib/Controller/OCSAuthAPIController.php
index fdca601da63..594299a2d02 100644
--- a/apps/federation/lib/Controller/OCSAuthAPIController.php
+++ b/apps/federation/lib/Controller/OCSAuthAPIController.php
@@ -94,6 +94,37 @@ class OCSAuthAPIController extends OCSController{
* @NoCSRFRequired
* @PublicPage
*
+ * request received to ask remote server for a shared secret, for legacy end-points
+ *
+ * @param string $url
+ * @param string $token
+ * @return Http\DataResponse
+ * @throws OCSForbiddenException
+ */
+ public function requestSharedSecretLegacy($url, $token) {
+ return $this->requestSharedSecret($url, $token);
+ }
+
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
+ * create shared secret and return it, for legacy end-points
+ *
+ * @param string $url
+ * @param string $token
+ * @return Http\DataResponse
+ * @throws OCSForbiddenException
+ */
+ public function getSharedSecretLegacy($url, $token) {
+ return $this->getSharedSecret($url, $token);
+ }
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* request received to ask remote server for a shared secret
*
* @param string $url
diff --git a/apps/federation/lib/SyncFederationAddressBooks.php b/apps/federation/lib/SyncFederationAddressBooks.php
index 759b59183aa..87419a5ba54 100644
--- a/apps/federation/lib/SyncFederationAddressBooks.php
+++ b/apps/federation/lib/SyncFederationAddressBooks.php
@@ -23,12 +23,10 @@
*/
namespace OCA\Federation;
+use OC\OCS\DiscoveryService;
use OCA\DAV\CardDAV\SyncService;
use OCP\AppFramework\Http;
-use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Helper\ProgressBar;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
+use OCP\OCS\IDiscoveryService;
class SyncFederationAddressBooks {
@@ -38,13 +36,21 @@ class SyncFederationAddressBooks {
/** @var SyncService */
private $syncService;
+ /** @var DiscoveryService */
+ private $ocsDiscoveryService;
+
/**
* @param DbHandler $dbHandler
* @param SyncService $syncService
+ * @param IDiscoveryService $ocsDiscoveryService
*/
- function __construct(DbHandler $dbHandler, SyncService $syncService) {
+ public function __construct(DbHandler $dbHandler,
+ SyncService $syncService,
+ IDiscoveryService $ocsDiscoveryService
+ ) {
$this->syncService = $syncService;
$this->dbHandler = $dbHandler;
+ $this->ocsDiscoveryService = $ocsDiscoveryService;
}
/**
@@ -59,6 +65,10 @@ class SyncFederationAddressBooks {
$sharedSecret = $trustedServer['shared_secret'];
$syncToken = $trustedServer['sync_token'];
+ $endPoints = $this->ocsDiscoveryService->discover($url, 'FEDERATED_SHARING');
+ $cardDavUser = isset($endPoints['carddav-user']) ? $endPoints['carddav-user'] : 'system';
+ $addressBookUrl = isset($endPoints['system-address-book']) ? trim($endPoints['system-address-book'], '/') : 'remote.php/dav/addressbooks/system/system/system';
+
if (is_null($sharedSecret)) {
continue;
}
@@ -68,7 +78,7 @@ class SyncFederationAddressBooks {
'{DAV:}displayname' => $url
];
try {
- $newToken = $this->syncService->syncRemoteAddressBook($url, 'system', $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetBookProperties);
+ $newToken = $this->syncService->syncRemoteAddressBook($url, $cardDavUser, $addressBookUrl, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetBookProperties);
if ($newToken !== $syncToken) {
$this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken);
}
diff --git a/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php b/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php
index fe7cc5cc337..6364ddaedff 100644
--- a/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php
+++ b/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php
@@ -36,6 +36,7 @@ use OCP\Http\Client\IClient;
use OCP\Http\Client\IResponse;
use OCP\ILogger;
use OCP\IURLGenerator;
+use OCP\OCS\IDiscoveryService;
/**
* Class GetSharedSecretTest
@@ -67,6 +68,9 @@ class GetSharedSecretTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
private $response;
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IDiscoveryService */
+ private $discoverService;
+
/** @var GetSharedSecret */
private $getSharedSecret;
@@ -82,6 +86,9 @@ class GetSharedSecretTest extends TestCase {
->disableOriginalConstructor()->getMock();
$this->logger = $this->getMockBuilder(ILogger::class)->getMock();
$this->response = $this->getMockBuilder(IResponse::class)->getMock();
+ $this->discoverService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
+
+ $this->discoverService->expects($this->any())->method('discover')->willReturn([]);
$this->getSharedSecret = new GetSharedSecret(
$this->httpClient,
@@ -89,7 +96,8 @@ class GetSharedSecretTest extends TestCase {
$this->jobList,
$this->trustedServers,
$this->logger,
- $this->dbHandler
+ $this->dbHandler,
+ $this->discoverService
);
}
@@ -109,7 +117,8 @@ class GetSharedSecretTest extends TestCase {
$this->jobList,
$this->trustedServers,
$this->logger,
- $this->dbHandler
+ $this->dbHandler,
+ $this->discoverService
]
)->setMethods(['parentExecute'])->getMock();
$this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url']]);
diff --git a/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php b/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php
index 3fa2ca2973e..06da29d17fc 100644
--- a/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php
+++ b/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php
@@ -33,6 +33,7 @@ use OCP\BackgroundJob\IJobList;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IResponse;
use OCP\IURLGenerator;
+use OCP\OCS\IDiscoveryService;
use Test\TestCase;
class RequestSharedSecretTest extends TestCase {
@@ -55,6 +56,9 @@ class RequestSharedSecretTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
private $response;
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IDiscoveryService */
+ private $discoveryService;
+
/** @var RequestSharedSecret */
private $requestSharedSecret;
@@ -69,13 +73,17 @@ class RequestSharedSecretTest extends TestCase {
$this->dbHandler = $this->getMockBuilder(DbHandler::class)
->disableOriginalConstructor()->getMock();
$this->response = $this->getMockBuilder(IResponse::class)->getMock();
+ $this->discoveryService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
+
+ $this->discoveryService->expects($this->any())->method('discover')->willReturn([]);
$this->requestSharedSecret = new RequestSharedSecret(
$this->httpClient,
$this->urlGenerator,
$this->jobList,
$this->trustedServers,
- $this->dbHandler
+ $this->dbHandler,
+ $this->discoveryService
);
}
@@ -94,7 +102,8 @@ class RequestSharedSecretTest extends TestCase {
$this->urlGenerator,
$this->jobList,
$this->trustedServers,
- $this->dbHandler
+ $this->dbHandler,
+ $this->discoveryService
]
)->setMethods(['parentExecute'])->getMock();
$this->invokePrivate($requestSharedSecret, 'argument', [['url' => 'url']]);
diff --git a/apps/federation/tests/SyncFederationAddressbooksTest.php b/apps/federation/tests/SyncFederationAddressbooksTest.php
index 1a2dbf1bcae..9ce5efeb457 100644
--- a/apps/federation/tests/SyncFederationAddressbooksTest.php
+++ b/apps/federation/tests/SyncFederationAddressbooksTest.php
@@ -24,6 +24,7 @@
*/
namespace OCA\Federation\Tests;
+use OC\OCS\DiscoveryService;
use OCA\Federation\DbHandler;
use OCA\Federation\SyncFederationAddressBooks;
@@ -32,7 +33,18 @@ class SyncFederationAddressbooksTest extends \Test\TestCase {
/** @var array */
private $callBacks = [];
- function testSync() {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | DiscoveryService */
+ private $discoveryService;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->discoveryService = $this->getMockBuilder(DiscoveryService::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->discoveryService->expects($this->any())->method('discover')->willReturn([]);
+ }
+
+ public function testSync() {
/** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $dbHandler */
$dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')->
disableOriginalConstructor()->
@@ -55,14 +67,14 @@ class SyncFederationAddressbooksTest extends \Test\TestCase {
->willReturn(1);
/** @var \OCA\DAV\CardDAV\SyncService $syncService */
- $s = new SyncFederationAddressBooks($dbHandler, $syncService);
+ $s = new SyncFederationAddressBooks($dbHandler, $syncService, $this->discoveryService);
$s->syncThemAll(function($url, $ex) {
$this->callBacks[] = [$url, $ex];
});
$this->assertEquals(1, count($this->callBacks));
}
- function testException() {
+ public function testException() {
/** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $dbHandler */
$dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')->
disableOriginalConstructor()->
@@ -83,7 +95,7 @@ class SyncFederationAddressbooksTest extends \Test\TestCase {
->willThrowException(new \Exception('something did not work out'));
/** @var \OCA\DAV\CardDAV\SyncService $syncService */
- $s = new SyncFederationAddressBooks($dbHandler, $syncService);
+ $s = new SyncFederationAddressBooks($dbHandler, $syncService, $this->discoveryService);
$s->syncThemAll(function($url, $ex) {
$this->callBacks[] = [$url, $ex];
});
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index f9540df3ff2..f502d905fe8 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -92,17 +92,13 @@ 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->getHTTPClientService(),
$server->getNotificationManager(),
- $discoveryManager,
+ $server->query(\OCP\OCS\IDiscoveryService::class),
$uid
);
});
diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php
index 0a57324c32f..2c348907384 100644
--- a/apps/files_sharing/lib/External/Manager.php
+++ b/apps/files_sharing/lib/External/Manager.php
@@ -32,8 +32,11 @@ namespace OCA\Files_Sharing\External;
use OC\Files\Filesystem;
use OCA\FederatedFileSharing\DiscoveryManager;
use OCP\Files;
+use OCP\Files\Storage\IStorageFactory;
use OCP\Http\Client\IClientService;
+use OCP\IDBConnection;
use OCP\Notification\IManager;
+use OCP\OCS\IDiscoveryService;
class Manager {
const STORAGE = '\OCA\Files_Sharing\External\Storage';
@@ -44,7 +47,7 @@ class Manager {
private $uid;
/**
- * @var \OCP\IDBConnection
+ * @var IDBConnection
*/
private $connection;
@@ -54,7 +57,7 @@ class Manager {
private $mountManager;
/**
- * @var \OCP\Files\Storage\IStorageFactory
+ * @var IStorageFactory
*/
private $storageLoader;
@@ -67,24 +70,27 @@ class Manager {
* @var IManager
*/
private $notificationManager;
- /** @var DiscoveryManager */
- private $discoveryManager;
/**
- * @param \OCP\IDBConnection $connection
+ * @var IDiscoveryService
+ */
+ private $discoveryService;
+
+ /**
+ * @param IDBConnection $connection
* @param \OC\Files\Mount\Manager $mountManager
- * @param \OCP\Files\Storage\IStorageFactory $storageLoader
+ * @param IStorageFactory $storageLoader
* @param IClientService $clientService
* @param IManager $notificationManager
- * @param DiscoveryManager $discoveryManager
+ * @param IDiscoveryService $discoveryService
* @param string $uid
*/
- public function __construct(\OCP\IDBConnection $connection,
+ public function __construct(IDBConnection $connection,
\OC\Files\Mount\Manager $mountManager,
- \OCP\Files\Storage\IStorageFactory $storageLoader,
+ IStorageFactory $storageLoader,
IClientService $clientService,
IManager $notificationManager,
- DiscoveryManager $discoveryManager,
+ IDiscoveryService $discoveryService,
$uid) {
$this->connection = $connection;
$this->mountManager = $mountManager;
@@ -92,7 +98,7 @@ class Manager {
$this->clientService = $clientService;
$this->uid = $uid;
$this->notificationManager = $notificationManager;
- $this->discoveryManager = $discoveryManager;
+ $this->discoveryService = $discoveryService;
}
/**
@@ -260,7 +266,10 @@ class Manager {
*/
private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
- $url = rtrim($remote, '/') . $this->discoveryManager->getShareEndpoint($remote) . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
+ $federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING');
+ $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
+
+ $url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
$fields = array('token' => $token);
$client = $this->clientService->newClient();
@@ -376,7 +385,7 @@ class Manager {
/**
* remove re-shares from share table and mapping in the federated_reshares table
- *
+ *
* @param $mountPointId
*/
protected function removeReShares($mountPointId) {
diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php
index 319735dcaf5..b84ba5d96ab 100644
--- a/apps/files_sharing/lib/External/Storage.php
+++ b/apps/files_sharing/lib/External/Storage.php
@@ -51,8 +51,6 @@ class Storage extends DAV implements ISharedStorage {
private $memcacheFactory;
/** @var \OCP\Http\Client\IClientService */
private $httpClient;
- /** @var \OCP\ICertificateManager */
- private $certificateManager;
/** @var bool */
private $updateChecked = false;
@@ -64,14 +62,11 @@ class Storage extends DAV implements ISharedStorage {
public function __construct($options) {
$this->memcacheFactory = \OC::$server->getMemCacheFactory();
$this->httpClient = $options['HttpClientService'];
- $discoveryManager = new DiscoveryManager(
- $this->memcacheFactory,
- $this->httpClient
- );
$this->manager = $options['manager'];
- $this->certificateManager = $options['certificateManager'];
$this->cloudId = $options['cloudId'];
+ $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
+
list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
if (strpos($remote, '/')) {
list($host, $root) = explode('/', $remote, 2);
@@ -80,9 +75,12 @@ class Storage extends DAV implements ISharedStorage {
$root = '';
}
$secure = $protocol === 'https';
- $root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->cloudId->getRemote());
+ $federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
+ $webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
+ $root = rtrim($root, '/') . $webDavEndpoint;
$this->mountPoint = $options['mountpoint'];
$this->token = $options['token'];
+
parent::__construct(array(
'secure' => $secure,
'host' => $host,
@@ -350,7 +348,7 @@ class Storage extends DAV implements ISharedStorage {
}
return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
}
-
+
public function getPermissions($path) {
$response = $this->propfind($path);
if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
diff --git a/apps/files_sharing/lib/Hooks.php b/apps/files_sharing/lib/Hooks.php
index 2029e97d08b..821c3046595 100644
--- a/apps/files_sharing/lib/Hooks.php
+++ b/apps/files_sharing/lib/Hooks.php
@@ -32,17 +32,13 @@ 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->getHTTPClientService(),
\OC::$server->getNotificationManager(),
- $discoveryManager,
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
$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 f2a55babcc7..9f60261c203 100644
--- a/apps/files_sharing/tests/External/ManagerTest.php
+++ b/apps/files_sharing/tests/External/ManagerTest.php
@@ -70,17 +70,14 @@ class ManagerTest extends TestCase {
$this->mountManager = new \OC\Files\Mount\Manager();
$this->clientService = $this->getMockBuilder('\OCP\Http\Client\IClientService')
->disableOriginalConstructor()->getMock();
- $discoveryManager = new DiscoveryManager(
- \OC::$server->getMemCacheFactory(),
- \OC::$server->getHTTPClientService()
- );
+
$this->manager = new Manager(
\OC::$server->getDatabaseConnection(),
$this->mountManager,
new StorageFactory(),
$this->clientService,
\OC::$server->getNotificationManager(),
- $discoveryManager,
+ \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
$this->uid
);
$this->testMountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() {
@@ -143,7 +140,7 @@ class ManagerTest extends TestCase {
->disableOriginalConstructor()->getMock();
$client->expects($this->once())
->method('post')
- ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id']), $this->anything())
+ ->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $openShares[0]['remote_id']), $this->anything())
->willReturn($response);
// Accept the first share
@@ -186,7 +183,7 @@ class ManagerTest extends TestCase {
->disableOriginalConstructor()->getMock();
$client->expects($this->once())
->method('post')
- ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[1]['remote_id'] . '/decline'), $this->anything())
+ ->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $openShares[1]['remote_id'] . '/decline'), $this->anything())
->willReturn($response);
// Decline the third share
@@ -226,11 +223,11 @@ class ManagerTest extends TestCase {
->disableOriginalConstructor()->getMock();
$client1->expects($this->once())
->method('post')
- ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id'] . '/decline'), $this->anything())
+ ->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $openShares[0]['remote_id'] . '/decline'), $this->anything())
->willReturn($response);
$client2->expects($this->once())
->method('post')
- ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $acceptedShares[0]['remote_id'] . '/decline'), $this->anything())
+ ->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $acceptedShares[0]['remote_id'] . '/decline'), $this->anything())
->willReturn($response);
$this->manager->removeUserShares($this->uid);
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index c80881262d7..ab6a3781147 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -220,6 +220,7 @@ return array(
'OCP\\Notification\\IManager' => $baseDir . '/lib/public/Notification/IManager.php',
'OCP\\Notification\\INotification' => $baseDir . '/lib/public/Notification/INotification.php',
'OCP\\Notification\\INotifier' => $baseDir . '/lib/public/Notification/INotifier.php',
+ 'OCP\\OCS\\IDiscoveryService' => $baseDir . '/lib/public/OCS/IDiscoveryService.php',
'OCP\\PreConditionNotMetException' => $baseDir . '/lib/public/PreConditionNotMetException.php',
'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php',
'OCP\\Response' => $baseDir . '/lib/public/Response.php',
@@ -662,6 +663,7 @@ return array(
'OC\\Notification\\Manager' => $baseDir . '/lib/private/Notification/Manager.php',
'OC\\Notification\\Notification' => $baseDir . '/lib/private/Notification/Notification.php',
'OC\\OCS\\CoreCapabilities' => $baseDir . '/lib/private/OCS/CoreCapabilities.php',
+ 'OC\\OCS\\DiscoveryService' => $baseDir . '/lib/private/OCS/DiscoveryService.php',
'OC\\OCS\\Exception' => $baseDir . '/lib/private/OCS/Exception.php',
'OC\\OCS\\PrivateData' => $baseDir . '/lib/private/OCS/PrivateData.php',
'OC\\OCS\\Provider' => $baseDir . '/lib/private/OCS/Provider.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 8955d2de6ce..1b2c9f84df8 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -250,6 +250,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Notification\\IManager' => __DIR__ . '/../../..' . '/lib/public/Notification/IManager.php',
'OCP\\Notification\\INotification' => __DIR__ . '/../../..' . '/lib/public/Notification/INotification.php',
'OCP\\Notification\\INotifier' => __DIR__ . '/../../..' . '/lib/public/Notification/INotifier.php',
+ 'OCP\\OCS\\IDiscoveryService' => __DIR__ . '/../../..' . '/lib/public/OCS/IDiscoveryService.php',
'OCP\\PreConditionNotMetException' => __DIR__ . '/../../..' . '/lib/public/PreConditionNotMetException.php',
'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php',
'OCP\\Response' => __DIR__ . '/../../..' . '/lib/public/Response.php',
@@ -692,6 +693,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Notification\\Manager' => __DIR__ . '/../../..' . '/lib/private/Notification/Manager.php',
'OC\\Notification\\Notification' => __DIR__ . '/../../..' . '/lib/private/Notification/Notification.php',
'OC\\OCS\\CoreCapabilities' => __DIR__ . '/../../..' . '/lib/private/OCS/CoreCapabilities.php',
+ 'OC\\OCS\\DiscoveryService' => __DIR__ . '/../../..' . '/lib/private/OCS/DiscoveryService.php',
'OC\\OCS\\Exception' => __DIR__ . '/../../..' . '/lib/private/OCS/Exception.php',
'OC\\OCS\\PrivateData' => __DIR__ . '/../../..' . '/lib/private/OCS/PrivateData.php',
'OC\\OCS\\Provider' => __DIR__ . '/../../..' . '/lib/private/OCS/Provider.php',
diff --git a/lib/private/OCS/DiscoveryService.php b/lib/private/OCS/DiscoveryService.php
new file mode 100644
index 00000000000..5534fb24ef5
--- /dev/null
+++ b/lib/private/OCS/DiscoveryService.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\OCS;
+
+use OCP\AppFramework\Http;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\OCS\IDiscoveryService;
+
+class DiscoveryService implements IDiscoveryService {
+
+ /** @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();
+ }
+
+
+ /**
+ * Discover OCS end-points
+ *
+ * If no valid discovery data is found the defaults are returned
+ *
+ * @param string $remote
+ * @param string $service the service you want to discover
+ * @return array
+ */
+ public function discover($remote, $service) {
+ // Check the cache first
+ $cacheData = $this->cache->get($remote . '#' . $service);
+ if($cacheData) {
+ return json_decode($cacheData, true);
+ }
+
+ $discoveredServices = [];
+
+ // query the remote server for available services
+ try {
+ $response = $this->client->get($remote . '/ocs-provider/', [
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ if($response->getStatusCode() === Http::STATUS_OK) {
+ $decodedServices = json_decode($response->getBody(), true);
+ $discoveredServices = $this->getEndpoints($decodedServices, $service);
+ }
+ } catch (\Exception $e) {
+ // if we couldn't discover the service or any end-points we return a empty array
+ return [];
+ }
+
+ // Write into cache
+ $this->cache->set($remote . '#' . $service, json_encode($discoveredServices));
+ return $discoveredServices;
+ }
+
+ /**
+ * get requested end-points from the requested service
+ *
+ * @param $decodedServices
+ * @param $service
+ * @return array
+ */
+ protected function getEndpoints($decodedServices, $service) {
+
+ $discoveredServices = [];
+
+ if(is_array($decodedServices) &&
+ isset($decodedServices['services'][$service]['endpoints'])
+ ) {
+ foreach ($decodedServices['services'][$service]['endpoints'] as $endpoint => $url) {
+ if($this->isSafeUrl($url)) {
+ $discoveredServices[$endpoint] = $url;
+ }
+ }
+ }
+
+ return $discoveredServices;
+ }
+
+ /**
+ * Returns whether the specified URL includes only safe characters, if not
+ * returns false
+ *
+ * @param string $url
+ * @return bool
+ */
+ protected function isSafeUrl($url) {
+ return (bool)preg_match('/^[\/\.\-A-Za-z0-9]+$/', $url);
+ }
+
+}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 011263cd2d8..00698a04f89 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -77,6 +77,7 @@ use OC\Mail\Mailer;
use OC\Memcache\ArrayCache;
use OC\Memcache\Factory;
use OC\Notification\Manager;
+use OC\OCS\DiscoveryService;
use OC\Repair\NC11\CleanPreviewsBackgroundJob;
use OC\RichObjectStrings\Validator;
use OC\Security\Bruteforce\Throttler;
@@ -938,6 +939,10 @@ class Server extends ServerContainer implements IServerContainer {
});
});
+ $this->registerService(\OCP\OCS\IDiscoveryService::class, function (Server $c) {
+ return new DiscoveryService($c->getMemCacheFactory(), $c->getHTTPClientService());
+ });
+
$this->registerService(ICloudIdManager::class, function (Server $c) {
return new CloudIdManager();
});
diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php
index 924e2f68396..b3e4cb2d4aa 100644
--- a/lib/private/Share/Share.php
+++ b/lib/private/Share/Share.php
@@ -2742,12 +2742,10 @@ class Share extends Constants {
'result' => '',
];
$try = 0;
- $discoveryManager = new DiscoveryManager(
- \OC::$server->getMemCacheFactory(),
- \OC::$server->getHTTPClientService()
- );
+ $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
while ($result['success'] === false && $try < 2) {
- $endpoint = $discoveryManager->getShareEndpoint($protocol . $remoteDomain);
+ $federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
+ $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
$result = \OC::$server->getHTTPHelper()->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, $fields);
$try++;
$protocol = 'http://';
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index b411f42b262..ba6699ae7ad 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -104,14 +104,10 @@ class ProviderFactory implements IProviderFactory {
$l,
$this->serverContainer->getCloudIdManager()
);
- $discoveryManager = new DiscoveryManager(
- $this->serverContainer->getMemCacheFactory(),
- $this->serverContainer->getHTTPClientService()
- );
$notifications = new Notifications(
$addressHandler,
$this->serverContainer->getHTTPClientService(),
- $discoveryManager,
+ $this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
$this->serverContainer->getJobList()
);
$tokenHandler = new TokenHandler(
diff --git a/lib/public/OCS/IDiscoveryService.php b/lib/public/OCS/IDiscoveryService.php
new file mode 100644
index 00000000000..eee5bf97f93
--- /dev/null
+++ b/lib/public/OCS/IDiscoveryService.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCP\OCS;
+
+/**
+ * Interface IDiscoveryService
+ *
+ * Allows you to discover OCS end-points on a remote server
+ *
+ * @package OCP\OCS
+ * @since 12.0.0
+ */
+interface IDiscoveryService {
+
+ /**
+ * Discover OCS end-points
+ *
+ * If no valid discovery data is found the defaults are returned
+ *
+ * @since 12.0.0
+ *
+ * @param string $remote
+ * @param string $service the service you want to discover
+ * @return array
+ */
+ public function discover($remote, $service);
+
+}
diff --git a/tests/lib/OCS/DiscoveryServiceTest.php b/tests/lib/OCS/DiscoveryServiceTest.php
new file mode 100644
index 00000000000..fdcdddb0813
--- /dev/null
+++ b/tests/lib/OCS/DiscoveryServiceTest.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace Test\OCS;
+
+
+use OC\OCS\DiscoveryService;
+use OCP\Http\Client\IClientService;
+use OCP\ICacheFactory;
+use OCP\OCS\IDiscoveryService;
+use Test\TestCase;
+
+class DiscoveryServiceTest extends TestCase {
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | ICacheFactory */
+ private $cacheFactory;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IClientService */
+ private $clientService;
+
+ /** @var IDiscoveryService */
+ private $discoveryService;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->cacheFactory = $this->getMockBuilder(ICacheFactory::class)->getMock();
+ $this->clientService = $this->getMockBuilder(IClientService::class)->getMock();
+
+ $this->discoveryService = new DiscoveryService(
+ $this->cacheFactory,
+ $this->clientService
+ );
+ }
+
+ /**
+ * @dataProvider dataTestIsSafeUrl
+ *
+ * @param string $url
+ * @param bool $expected
+ */
+ public function testIsSafeUrl($url, $expected) {
+ $result = $this->invokePrivate($this->discoveryService, 'isSafeUrl', [$url]);
+ $this->assertSame($expected, $result);
+ }
+
+ public function dataTestIsSafeUrl() {
+ return [
+ ['api/ocs/v1.php/foo', true],
+ ['/api/ocs/v1.php/foo', true],
+ ['api/ocs/v1.php/foo/', true],
+ ['api/ocs/v1.php/foo-bar/', true],
+ ['api/ocs/v1:php/foo', false],
+ ['api/ocs/<v1.php/foo', false],
+ ['api/ocs/v1.php>/foo', false],
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestGetEndpoints
+ *
+ * @param array $decodedServices
+ * @param string $service
+ * @param array $expected
+ */
+ public function testGetEndpoints($decodedServices, $service, $expected) {
+ $result = $this->invokePrivate($this->discoveryService, 'getEndpoints', [$decodedServices, $service]);
+ $this->assertSame($expected, $result);
+ }
+
+ public function dataTestGetEndpoints() {
+ return [
+ [['services' => ['myService' => ['endpoints' => []]]], 'myService', []],
+ [['services' => ['myService' => ['endpoints' => ['foo' => '/bar']]]], 'myService', ['foo' => '/bar']],
+ [['services' => ['myService' => ['endpoints' => ['foo' => '/bar']]]], 'anotherService', []],
+ [['services' => ['myService' => ['endpoints' => ['foo' => '/bar</foo']]]], 'myService', []],
+ ];
+ }
+
+}
diff --git a/tests/lib/Share/ShareTest.php b/tests/lib/Share/ShareTest.php
index 6b0ebd76ed7..40e88d597a4 100644
--- a/tests/lib/Share/ShareTest.php
+++ b/tests/lib/Share/ShareTest.php
@@ -1064,11 +1064,11 @@ class ShareTest extends \Test\TestCase {
$httpHelperMock->expects($this->at(0))
->method('post')
- ->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v1.php/cloud/shares'), $this->anything())
+ ->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v2.php/cloud/shares'), $this->anything())
->willReturn(['success' => false, 'result' => 'Exception']);
$httpHelperMock->expects($this->at(1))
->method('post')
- ->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v1.php/cloud/shares'), $this->anything())
+ ->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v2.php/cloud/shares'), $this->anything())
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
\OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, $shareWith, \OCP\Constants::PERMISSION_READ);
@@ -1077,11 +1077,11 @@ class ShareTest extends \Test\TestCase {
$httpHelperMock->expects($this->at(0))
->method('post')
- ->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v1.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
+ ->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v2.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
->willReturn(['success' => false, 'result' => 'Exception']);
$httpHelperMock->expects($this->at(1))
->method('post')
- ->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v1.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
+ ->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v2.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
\OCP\Share::unshare('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, $shareWith);
@@ -1490,7 +1490,7 @@ class ShareTest extends \Test\TestCase {
$httpHelperMock->expects($this->at(0))
->method('post')
- ->with($this->stringStartsWith('https://localhost/ocs/v1.php/cloud/shares'), $this->anything())
+ ->with($this->stringStartsWith('https://localhost/ocs/v2.php/cloud/shares'), $this->anything())
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
\OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, 'foo@localhost', \OCP\Constants::PERMISSION_READ);
@@ -1507,7 +1507,7 @@ class ShareTest extends \Test\TestCase {
$httpHelperMock->expects($this->at(0))
->method('post')
- ->with($this->stringStartsWith('https://localhost/ocs/v1.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
+ ->with($this->stringStartsWith('https://localhost/ocs/v2.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
\OCP\Share::unshare('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, 'foo@localhost');