Signed-off-by: Robin Appelman <robin@icewind.nl>tags/v12.0.0beta1
@@ -22,6 +22,7 @@ | |||
namespace OCA\FederatedFileSharing; | |||
use OC\HintException; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\IL10N; | |||
use OCP\IURLGenerator; | |||
@@ -38,18 +39,24 @@ class AddressHandler { | |||
/** @var IURLGenerator */ | |||
private $urlGenerator; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
/** | |||
* AddressHandler constructor. | |||
* | |||
* @param IURLGenerator $urlGenerator | |||
* @param IL10N $il10n | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct( | |||
IURLGenerator $urlGenerator, | |||
IL10N $il10n | |||
IL10N $il10n, | |||
ICloudIdManager $cloudIdManager | |||
) { | |||
$this->l = $il10n; | |||
$this->urlGenerator = $urlGenerator; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
@@ -60,44 +67,13 @@ class AddressHandler { | |||
* @throws HintException | |||
*/ | |||
public function splitUserRemote($address) { | |||
if (strpos($address, '@') === false) { | |||
try { | |||
$cloudId = $this->cloudIdManager->resolveCloudId($address); | |||
return [$cloudId->getUser(), $cloudId->getRemote()]; | |||
} catch (\InvalidArgumentException $e) { | |||
$hint = $this->l->t('Invalid Federated Cloud ID'); | |||
throw new HintException('Invalid Federated Cloud ID', $hint); | |||
} | |||
// Find the first character that is not allowed in user names | |||
$id = str_replace('\\', '/', $address); | |||
$posSlash = strpos($id, '/'); | |||
$posColon = strpos($id, ':'); | |||
if ($posSlash === false && $posColon === false) { | |||
$invalidPos = strlen($id); | |||
} else if ($posSlash === false) { | |||
$invalidPos = $posColon; | |||
} else if ($posColon === false) { | |||
$invalidPos = $posSlash; | |||
} else { | |||
$invalidPos = min($posSlash, $posColon); | |||
} | |||
// Find the last @ before $invalidPos | |||
$pos = $lastAtPos = 0; | |||
while ($lastAtPos !== false && $lastAtPos <= $invalidPos) { | |||
$pos = $lastAtPos; | |||
$lastAtPos = strpos($id, '@', $pos + 1); | |||
throw new HintException('Invalid Federated Cloud ID', $hint, 0, $e); | |||
} | |||
if ($pos !== false) { | |||
$user = substr($id, 0, $pos); | |||
$remote = substr($id, $pos + 1); | |||
$remote = $this->fixRemoteURL($remote); | |||
if (!empty($user) && !empty($remote)) { | |||
return array($user, $remote); | |||
} | |||
} | |||
$hint = $this->l->t('Invalid Federated Cloud ID'); | |||
throw new HintException('Invalid Federated Cloud ID', $hint); | |||
} | |||
/** | |||
@@ -175,27 +151,4 @@ class AddressHandler { | |||
return false; | |||
} | |||
/** | |||
* Strips away a potential file names and trailing slashes: | |||
* - http://localhost | |||
* - http://localhost/ | |||
* - http://localhost/index.php | |||
* - http://localhost/index.php/s/{shareToken} | |||
* | |||
* all return: http://localhost | |||
* | |||
* @param string $remote | |||
* @return string | |||
*/ | |||
protected function fixRemoteURL($remote) { | |||
$remote = str_replace('\\', '/', $remote); | |||
if ($fileNamePosition = strpos($remote, '/index.php')) { | |||
$remote = substr($remote, 0, $fileNamePosition); | |||
} | |||
$remote = rtrim($remote, '/'); | |||
return $remote; | |||
} | |||
} |
@@ -45,7 +45,8 @@ class Application extends App { | |||
$container->registerService('RequestHandlerController', function(SimpleContainer $c) use ($server) { | |||
$addressHandler = new AddressHandler( | |||
$server->getURLGenerator(), | |||
$server->getL10N('federatedfilesharing') | |||
$server->getL10N('federatedfilesharing'), | |||
$server->getCloudIdManager() | |||
); | |||
$notification = new Notifications( | |||
$addressHandler, | |||
@@ -64,7 +65,8 @@ class Application extends App { | |||
$server->getShareManager(), | |||
$notification, | |||
$addressHandler, | |||
$server->getUserManager() | |||
$server->getUserManager(), | |||
$server->getCloudIdManager() | |||
); | |||
}); | |||
} | |||
@@ -94,7 +96,8 @@ class Application extends App { | |||
protected function initFederatedShareProvider() { | |||
$addressHandler = new \OCA\FederatedFileSharing\AddressHandler( | |||
\OC::$server->getURLGenerator(), | |||
\OC::$server->getL10N('federatedfilesharing') | |||
\OC::$server->getL10N('federatedfilesharing'), | |||
\OC::$server->getCloudIdManager() | |||
); | |||
$discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager( | |||
\OC::$server->getMemCacheFactory(), | |||
@@ -119,7 +122,8 @@ class Application extends App { | |||
\OC::$server->getLogger(), | |||
\OC::$server->getLazyRootFolder(), | |||
\OC::$server->getConfig(), | |||
\OC::$server->getUserManager() | |||
\OC::$server->getUserManager(), | |||
\OC::$server->getCloudIdManager() | |||
); | |||
} | |||
@@ -65,7 +65,8 @@ class RetryJob extends Job { | |||
} else { | |||
$addressHandler = new AddressHandler( | |||
\OC::$server->getURLGenerator(), | |||
\OC::$server->getL10N('federatedfilesharing') | |||
\OC::$server->getL10N('federatedfilesharing'), | |||
\OC::$server->getCloudIdManager() | |||
); | |||
$discoveryManager = new DiscoveryManager( | |||
\OC::$server->getMemCacheFactory(), |
@@ -35,6 +35,7 @@ use OCA\Files_Sharing\External\Manager; | |||
use OCP\AppFramework\Controller; | |||
use OCP\AppFramework\Http; | |||
use OCP\AppFramework\Http\JSONResponse; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Files\StorageInvalidException; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\IL10N; | |||
@@ -74,6 +75,9 @@ class MountPublicLinkController extends Controller { | |||
/** @var IClientService */ | |||
private $clientService; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
/** | |||
* MountPublicLinkController constructor. | |||
* | |||
@@ -86,6 +90,7 @@ class MountPublicLinkController extends Controller { | |||
* @param IL10N $l | |||
* @param IUserSession $userSession | |||
* @param IClientService $clientService | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct($appName, | |||
IRequest $request, | |||
@@ -95,7 +100,8 @@ class MountPublicLinkController extends Controller { | |||
ISession $session, | |||
IL10N $l, | |||
IUserSession $userSession, | |||
IClientService $clientService | |||
IClientService $clientService, | |||
ICloudIdManager $cloudIdManager | |||
) { | |||
parent::__construct($appName, $request); | |||
@@ -106,6 +112,7 @@ class MountPublicLinkController extends Controller { | |||
$this->l = $l; | |||
$this->userSession = $userSession; | |||
$this->clientService = $clientService; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
@@ -177,7 +184,7 @@ class MountPublicLinkController extends Controller { | |||
return new JSONResponse(['message' => $this->l->t('Server to server sharing is not enabled on this server')], Http::STATUS_BAD_REQUEST); | |||
} | |||
$shareWith = $this->userSession->getUser()->getUID() . '@' . $this->addressHandler->generateRemoteURL(); | |||
$cloudId = $this->cloudIdManager->getCloudId($this->userSession->getUser()->getUID(), $this->addressHandler->generateRemoteURL()); | |||
$httpClient = $this->clientService->newClient(); | |||
@@ -187,7 +194,7 @@ class MountPublicLinkController extends Controller { | |||
'body' => | |||
[ | |||
'token' => $token, | |||
'shareWith' => rtrim($shareWith, '/'), | |||
'shareWith' => rtrim($cloudId->getId(), '/'), | |||
'password' => $password | |||
], | |||
'connect_timeout' => 10, |
@@ -38,6 +38,7 @@ use OCP\AppFramework\OCS\OCSForbiddenException; | |||
use OCP\AppFramework\OCS\OCSNotFoundException; | |||
use OCP\AppFramework\OCSController; | |||
use OCP\Constants; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Files\NotFoundException; | |||
use OCP\IDBConnection; | |||
use OCP\IRequest; | |||
@@ -68,6 +69,9 @@ class RequestHandlerController extends OCSController { | |||
/** @var string */ | |||
private $shareTable = 'share'; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
/** | |||
* Server2Server constructor. | |||
* | |||
@@ -79,6 +83,7 @@ class RequestHandlerController extends OCSController { | |||
* @param Notifications $notifications | |||
* @param AddressHandler $addressHandler | |||
* @param IUserManager $userManager | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct($appName, | |||
IRequest $request, | |||
@@ -87,7 +92,8 @@ class RequestHandlerController extends OCSController { | |||
Share\IManager $shareManager, | |||
Notifications $notifications, | |||
AddressHandler $addressHandler, | |||
IUserManager $userManager | |||
IUserManager $userManager, | |||
ICloudIdManager $cloudIdManager | |||
) { | |||
parent::__construct($appName, $request); | |||
@@ -97,6 +103,7 @@ class RequestHandlerController extends OCSController { | |||
$this->notifications = $notifications; | |||
$this->addressHandler = $addressHandler; | |||
$this->userManager = $userManager; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
@@ -164,7 +171,7 @@ class RequestHandlerController extends OCSController { | |||
$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external'); | |||
if ($ownerFederatedId === null) { | |||
$ownerFederatedId = $owner . '@' . $this->cleanupRemote($remote); | |||
$ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId(); | |||
} | |||
// if the owner of the share and the initiator are the same user | |||
// we also complete the federated share ID for the initiator | |||
@@ -424,7 +431,7 @@ class RequestHandlerController extends OCSController { | |||
$remote = $this->cleanupRemote($share['remote']); | |||
$owner = $share['owner'] . '@' . $remote; | |||
$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote); | |||
$mountpoint = $share['mountpoint']; | |||
$user = $share['user']; | |||
@@ -27,6 +27,7 @@ | |||
namespace OCA\FederatedFileSharing; | |||
use OC\Share20\Share; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Files\Folder; | |||
use OCP\Files\IRootFolder; | |||
use OCP\IConfig; | |||
@@ -80,6 +81,9 @@ class FederatedShareProvider implements IShareProvider { | |||
/** @var IUserManager */ | |||
private $userManager; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
/** | |||
* DefaultShareProvider constructor. | |||
* | |||
@@ -92,6 +96,7 @@ class FederatedShareProvider implements IShareProvider { | |||
* @param IRootFolder $rootFolder | |||
* @param IConfig $config | |||
* @param IUserManager $userManager | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct( | |||
IDBConnection $connection, | |||
@@ -102,7 +107,8 @@ class FederatedShareProvider implements IShareProvider { | |||
ILogger $logger, | |||
IRootFolder $rootFolder, | |||
IConfig $config, | |||
IUserManager $userManager | |||
IUserManager $userManager, | |||
ICloudIdManager $cloudIdManager | |||
) { | |||
$this->dbConnection = $connection; | |||
$this->addressHandler = $addressHandler; | |||
@@ -113,6 +119,7 @@ class FederatedShareProvider implements IShareProvider { | |||
$this->rootFolder = $rootFolder; | |||
$this->config = $config; | |||
$this->userManager = $userManager; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
@@ -153,17 +160,18 @@ class FederatedShareProvider implements IShareProvider { | |||
// don't allow federated shares if source and target server are the same | |||
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith); | |||
$cloudId = $this->cloudIdManager->resolveCloudId($shareWith); | |||
$currentServer = $this->addressHandler->generateRemoteURL(); | |||
$currentUser = $sharedBy; | |||
if ($this->addressHandler->compareAddresses($user, $remote, $currentUser, $currentServer)) { | |||
if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) { | |||
$message = 'Not allowed to create a federated share with the same user.'; | |||
$message_t = $this->l->t('Not allowed to create a federated share with the same user'); | |||
$this->logger->debug($message, ['app' => 'Federated File Sharing']); | |||
throw new \Exception($message_t); | |||
} | |||
$share->setSharedWith($user . '@' . $remote); | |||
$share->setSharedWith(rtrim($cloudId->getId(), '/')); | |||
try { | |||
$remoteShare = $this->getShareFromExternalShareTable($share); | |||
@@ -173,8 +181,8 @@ class FederatedShareProvider implements IShareProvider { | |||
if ($remoteShare) { | |||
try { | |||
$uidOwner = $remoteShare['owner'] . '@' . $remoteShare['remote']; | |||
$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, 'tmp_token_' . time()); | |||
$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']); | |||
$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time()); | |||
$share->setId($shareId); | |||
list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId); | |||
// remote share was create successfully if we get a valid token as return | |||
@@ -227,15 +235,17 @@ class FederatedShareProvider implements IShareProvider { | |||
try { | |||
$sharedByFederatedId = $share->getSharedBy(); | |||
if ($this->userManager->userExists($sharedByFederatedId)) { | |||
$sharedByFederatedId = $sharedByFederatedId . '@' . $this->addressHandler->generateRemoteURL(); | |||
$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL()); | |||
$sharedByFederatedId = $cloudId->getId(); | |||
} | |||
$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL()); | |||
$send = $this->notifications->sendRemoteShare( | |||
$token, | |||
$share->getSharedWith(), | |||
$share->getNode()->getName(), | |||
$shareId, | |||
$share->getShareOwner(), | |||
$share->getShareOwner() . '@' . $this->addressHandler->generateRemoteURL(), | |||
$ownerCloudId->getId(), | |||
$share->getSharedBy(), | |||
$sharedByFederatedId | |||
); |
@@ -27,6 +27,8 @@ namespace OCA\FederatedFileSharing; | |||
use OC\HintException; | |||
use OC\Share\Helper; | |||
use OCP\Contacts\IManager; | |||
use OCP\Federation\ICloudId; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\IURLGenerator; | |||
use OCP\L10N\IFactory; | |||
use OCP\Notification\INotification; | |||
@@ -41,16 +43,20 @@ class Notifier implements INotifier { | |||
protected $url; | |||
/** @var array */ | |||
protected $federatedContacts; | |||
/** @var ICloudIdManager */ | |||
protected $cloudIdManager; | |||
/** | |||
* @param IFactory $factory | |||
* @param IManager $contactsManager | |||
* @param IURLGenerator $url | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct(IFactory $factory, IManager $contactsManager, IURLGenerator $url) { | |||
public function __construct(IFactory $factory, IManager $contactsManager, IURLGenerator $url, ICloudIdManager $cloudIdManager) { | |||
$this->factory = $factory; | |||
$this->contactsManager = $contactsManager; | |||
$this->url = $url; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
@@ -140,8 +146,10 @@ class Notifier implements INotifier { | |||
protected function createRemoteUser($cloudId) { | |||
$displayName = $cloudId; | |||
try { | |||
list($user, $server) = Helper::splitUserRemote($cloudId); | |||
$displayName = $this->getDisplayName($user, $server); | |||
$resolvedId = $this->cloudIdManager->resolveCloudId($cloudId); | |||
$displayName = $this->getDisplayName($resolvedId); | |||
$user = $resolvedId->getUser(); | |||
$server = $resolvedId->getRemote(); | |||
} catch (HintException $e) { | |||
$user = $cloudId; | |||
$server = ''; | |||
@@ -158,14 +166,12 @@ class Notifier implements INotifier { | |||
/** | |||
* Try to find the user in the contacts | |||
* | |||
* @param string $user | |||
* @param string $server | |||
* @param ICloudId $cloudId | |||
* @return string | |||
* @throws \OutOfBoundsException when there is no contact for the id | |||
*/ | |||
protected function getDisplayName($user, $server) { | |||
$server = strtolower(rtrim($server, '/')); | |||
protected function getDisplayName(ICloudId $cloudId) { | |||
$server = $cloudId->getRemote(); | |||
$user = $cloudId->getUser(); | |||
if (strpos($server, 'http://') === 0) { | |||
$server = substr($server, strlen('http://')); | |||
} else if (strpos($server, 'https://') === 0) { | |||
@@ -173,7 +179,7 @@ class Notifier implements INotifier { | |||
} | |||
try { | |||
return $this->getDisplayNameFromContact($user . '@' . $server); | |||
return $this->getDisplayNameFromContact($cloudId->getId()); | |||
} catch (\OutOfBoundsException $e) { | |||
} | |||
@@ -187,7 +193,7 @@ class Notifier implements INotifier { | |||
} catch (\OutOfBoundsException $e) { | |||
} | |||
return $user . '@' . $server; | |||
return $cloudId->getId(); | |||
} | |||
/** |
@@ -25,6 +25,7 @@ | |||
namespace OCA\FederatedFileSharing\Tests; | |||
use OC\Federation\CloudIdManager; | |||
use OCA\FederatedFileSharing\AddressHandler; | |||
use OCP\IL10N; | |||
use OCP\IURLGenerator; | |||
@@ -40,6 +41,9 @@ class AddressHandlerTest extends \Test\TestCase { | |||
/** @var IL10N | \PHPUnit_Framework_MockObject_MockObject */ | |||
private $il10n; | |||
/** @var CloudIdManager */ | |||
private $cloudIdManager; | |||
public function setUp() { | |||
parent::setUp(); | |||
@@ -48,7 +52,9 @@ class AddressHandlerTest extends \Test\TestCase { | |||
$this->il10n = $this->getMockBuilder('OCP\IL10N') | |||
->getMock(); | |||
$this->addressHandler = new AddressHandler($this->urlGenerator, $this->il10n); | |||
$this->cloudIdManager = new CloudIdManager(); | |||
$this->addressHandler = new AddressHandler($this->urlGenerator, $this->il10n, $this->cloudIdManager); | |||
} | |||
public function dataTestSplitUserRemote() { |
@@ -25,11 +25,13 @@ | |||
namespace OCA\FederatedFileSharing\Tests\Controller; | |||
use OC\Federation\CloudIdManager; | |||
use OC\HintException; | |||
use OCA\FederatedFileSharing\AddressHandler; | |||
use OCA\FederatedFileSharing\Controller\MountPublicLinkController; | |||
use OCA\FederatedFileSharing\FederatedShareProvider; | |||
use OCP\AppFramework\Http; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Files\IRootFolder; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\IL10N; | |||
@@ -77,6 +79,9 @@ class MountPublicLinkControllerTest extends \Test\TestCase { | |||
/** @var IShare */ | |||
private $share; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
public function setUp() { | |||
parent::setUp(); | |||
@@ -93,6 +98,7 @@ class MountPublicLinkControllerTest extends \Test\TestCase { | |||
$this->l10n = $this->getMockBuilder('OCP\IL10N')->disableOriginalConstructor()->getMock(); | |||
$this->userSession = $this->getMockBuilder('OCP\IUserSession')->disableOriginalConstructor()->getMock(); | |||
$this->clientService = $this->getMockBuilder('OCP\Http\Client\IClientService')->disableOriginalConstructor()->getMock(); | |||
$this->cloudIdManager = new CloudIdManager(); | |||
$this->controller = new MountPublicLinkController( | |||
'federatedfilesharing', $this->request, | |||
@@ -102,7 +108,8 @@ class MountPublicLinkControllerTest extends \Test\TestCase { | |||
$this->session, | |||
$this->l10n, | |||
$this->userSession, | |||
$this->clientService | |||
$this->clientService, | |||
$this->cloudIdManager | |||
); | |||
} | |||
@@ -27,10 +27,12 @@ | |||
namespace OCA\FederatedFileSharing\Tests; | |||
use OC\Federation\CloudIdManager; | |||
use OC\Files\Filesystem; | |||
use OCA\FederatedFileSharing\DiscoveryManager; | |||
use OCA\FederatedFileSharing\FederatedShareProvider; | |||
use OCA\FederatedFileSharing\Controller\RequestHandlerController; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Http\Client\IClient; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\Http\Client\IResponse; | |||
@@ -72,6 +74,9 @@ class RequestHandlerControllerTest extends TestCase { | |||
/** @var IShare|\PHPUnit_Framework_MockObject_MockObject */ | |||
private $share; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
protected function setUp() { | |||
parent::setUp(); | |||
@@ -100,6 +105,8 @@ class RequestHandlerControllerTest extends TestCase { | |||
$this->addressHandler = $this->getMockBuilder('OCA\FederatedFileSharing\AddressHandler') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock(); | |||
$this->cloudIdManager = new CloudIdManager(); | |||
$this->registerHttpHelper($httpHelperMock); | |||
@@ -111,7 +118,8 @@ class RequestHandlerControllerTest extends TestCase { | |||
\OC::$server->getShareManager(), | |||
$this->notifications, | |||
$this->addressHandler, | |||
$this->userManager | |||
$this->userManager, | |||
$this->cloudIdManager | |||
); | |||
$this->connection = \OC::$server->getDatabaseConnection(); | |||
@@ -190,7 +198,8 @@ class RequestHandlerControllerTest extends TestCase { | |||
\OC::$server->getShareManager(), | |||
$this->notifications, | |||
$this->addressHandler, | |||
$this->userManager | |||
$this->userManager, | |||
$this->cloudIdManager | |||
] | |||
)->setMethods(['executeDeclineShare', 'verifyShare'])->getMock(); | |||
@@ -25,10 +25,12 @@ | |||
namespace OCA\FederatedFileSharing\Tests; | |||
use OC\Federation\CloudIdManager; | |||
use OCA\FederatedFileSharing\AddressHandler; | |||
use OCA\FederatedFileSharing\FederatedShareProvider; | |||
use OCA\FederatedFileSharing\Notifications; | |||
use OCA\FederatedFileSharing\TokenHandler; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Files\IRootFolder; | |||
use OCP\IConfig; | |||
use OCP\IDBConnection; | |||
@@ -69,6 +71,9 @@ class FederatedShareProviderTest extends \Test\TestCase { | |||
/** @var FederatedShareProvider */ | |||
protected $provider; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
public function setUp() { | |||
parent::setUp(); | |||
@@ -94,6 +99,8 @@ class FederatedShareProviderTest extends \Test\TestCase { | |||
$this->userManager->expects($this->any())->method('userExists')->willReturn(true); | |||
$this->cloudIdManager = new CloudIdManager(); | |||
$this->provider = new FederatedShareProvider( | |||
$this->connection, | |||
$this->addressHandler, | |||
@@ -103,7 +110,8 @@ class FederatedShareProviderTest extends \Test\TestCase { | |||
$this->logger, | |||
$this->rootFolder, | |||
$this->config, | |||
$this->userManager | |||
$this->userManager, | |||
$this->cloudIdManager | |||
); | |||
$this->shareManager = \OC::$server->getShareManager(); | |||
@@ -400,7 +408,8 @@ class FederatedShareProviderTest extends \Test\TestCase { | |||
$this->logger, | |||
$this->rootFolder, | |||
$this->config, | |||
$this->userManager | |||
$this->userManager, | |||
$this->cloudIdManager | |||
] | |||
)->setMethods(['sendPermissionUpdate'])->getMock(); | |||
@@ -24,17 +24,38 @@ namespace OCA\Files_Sharing\Activity\Providers; | |||
use OCP\Activity\IEvent; | |||
use OCP\Activity\IManager; | |||
use OCP\Activity\IProvider; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\IL10N; | |||
use OCP\IURLGenerator; | |||
use OCP\IUserManager; | |||
use OCP\L10N\IFactory; | |||
class RemoteShares extends Base { | |||
protected $cloudIdManager; | |||
const SUBJECT_REMOTE_SHARE_ACCEPTED = 'remote_share_accepted'; | |||
const SUBJECT_REMOTE_SHARE_DECLINED = 'remote_share_declined'; | |||
const SUBJECT_REMOTE_SHARE_RECEIVED = 'remote_share_received'; | |||
const SUBJECT_REMOTE_SHARE_UNSHARED = 'remote_share_unshared'; | |||
/** | |||
* @param IFactory $languageFactory | |||
* @param IURLGenerator $url | |||
* @param IManager $activityManager | |||
* @param IUserManager $userManager | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct(IFactory $languageFactory, | |||
IURLGenerator $url, | |||
IManager $activityManager, | |||
IUserManager $userManager, | |||
ICloudIdManager $cloudIdManager | |||
) { | |||
parent::__construct($languageFactory, $url, $activityManager, $userManager); | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
* @param IEvent $event | |||
* @return IEvent | |||
@@ -115,12 +136,12 @@ class RemoteShares extends Base { | |||
* @return array | |||
*/ | |||
protected function getFederatedUser($cloudId) { | |||
$remoteUser = explode('@', $cloudId, 2); | |||
$remoteUser = $this->cloudIdManager->resolveCloudId($cloudId); | |||
return [ | |||
'type' => 'user', | |||
'id' => $remoteUser[0], | |||
'id' => $remoteUser->getUser(), | |||
'name' => $cloudId,// Todo display name from contacts | |||
'server' => $remoteUser[1], | |||
'server' => $remoteUser->getRemote(), | |||
]; | |||
} | |||
} |
@@ -145,7 +145,8 @@ class Application extends App { | |||
$server->getDatabaseConnection(), | |||
function() use ($c) { | |||
return $c->query('ExternalManager'); | |||
} | |||
}, | |||
$server->getCloudIdManager() | |||
); | |||
}); | |||
@@ -28,6 +28,7 @@ use OCP\AppFramework\Http; | |||
use OCP\AppFramework\OCS\OCSBadRequestException; | |||
use OCP\AppFramework\OCSController; | |||
use OCP\Contacts\IManager; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\IGroup; | |||
use OCP\IGroupManager; | |||
@@ -69,6 +70,9 @@ class ShareesAPIController extends OCSController { | |||
/** @var IClientService */ | |||
protected $clientService; | |||
/** @var ICloudIdManager */ | |||
protected $cloudIdManager; | |||
/** @var bool */ | |||
protected $shareWithGroupOnly = false; | |||
@@ -110,6 +114,7 @@ class ShareesAPIController extends OCSController { | |||
* @param ILogger $logger | |||
* @param \OCP\Share\IManager $shareManager | |||
* @param IClientService $clientService | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct($appName, | |||
IRequest $request, | |||
@@ -121,7 +126,9 @@ class ShareesAPIController extends OCSController { | |||
IURLGenerator $urlGenerator, | |||
ILogger $logger, | |||
\OCP\Share\IManager $shareManager, | |||
IClientService $clientService) { | |||
IClientService $clientService, | |||
ICloudIdManager $cloudIdManager | |||
) { | |||
parent::__construct($appName, $request); | |||
$this->groupManager = $groupManager; | |||
@@ -133,6 +140,7 @@ class ShareesAPIController extends OCSController { | |||
$this->logger = $logger; | |||
$this->shareManager = $shareManager; | |||
$this->clientService = $clientService; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
/** | |||
@@ -339,7 +347,7 @@ class ShareesAPIController extends OCSController { | |||
$result['results'] = []; | |||
} | |||
if (!$result['exactIdMatch'] && substr_count($search, '@') >= 1 && $this->offset === 0) { | |||
if (!$result['exactIdMatch'] && $this->cloudIdManager->isValidCloudId($search) && $this->offset === 0) { | |||
$result['exact'][] = [ | |||
'label' => $search, | |||
'value' => [ | |||
@@ -362,42 +370,12 @@ class ShareesAPIController extends OCSController { | |||
* @throws \Exception | |||
*/ | |||
public function splitUserRemote($address) { | |||
if (strpos($address, '@') === false) { | |||
throw new \Exception('Invalid Federated Cloud ID'); | |||
} | |||
// Find the first character that is not allowed in user names | |||
$id = str_replace('\\', '/', $address); | |||
$posSlash = strpos($id, '/'); | |||
$posColon = strpos($id, ':'); | |||
if ($posSlash === false && $posColon === false) { | |||
$invalidPos = strlen($id); | |||
} else if ($posSlash === false) { | |||
$invalidPos = $posColon; | |||
} else if ($posColon === false) { | |||
$invalidPos = $posSlash; | |||
} else { | |||
$invalidPos = min($posSlash, $posColon); | |||
} | |||
// Find the last @ before $invalidPos | |||
$pos = $lastAtPos = 0; | |||
while ($lastAtPos !== false && $lastAtPos <= $invalidPos) { | |||
$pos = $lastAtPos; | |||
$lastAtPos = strpos($id, '@', $pos + 1); | |||
} | |||
if ($pos !== false) { | |||
$user = substr($id, 0, $pos); | |||
$remote = substr($id, $pos + 1); | |||
$remote = $this->fixRemoteURL($remote); | |||
if (!empty($user) && !empty($remote)) { | |||
return array($user, $remote); | |||
} | |||
try { | |||
$cloudId = $this->cloudIdManager->resolveCloudId($address); | |||
return [$cloudId->getUser(), $cloudId->getRemote()]; | |||
} catch (\InvalidArgumentException $e) { | |||
throw new \Exception('Invalid Federated Cloud ID', 0, $e); | |||
} | |||
throw new \Exception('Invalid Federated Cloud ID'); | |||
} | |||
/** |
@@ -24,21 +24,25 @@ | |||
namespace OCA\Files_Sharing\External; | |||
use OCP\Federation\ICloudId; | |||
class Cache extends \OC\Files\Cache\Cache { | |||
/** @var ICloudId */ | |||
private $cloudId; | |||
private $remote; | |||
private $remoteUser; | |||
private $storage; | |||
/** | |||
* @param \OCA\Files_Sharing\External\Storage $storage | |||
* @param string $remote | |||
* @param string $remoteUser | |||
* @param ICloudId $cloudId | |||
*/ | |||
public function __construct($storage, $remote, $remoteUser) { | |||
public function __construct($storage, ICloudId $cloudId) { | |||
$this->cloudId = $cloudId; | |||
$this->storage = $storage; | |||
list(, $remote) = explode('://', $remote, 2); | |||
list(, $remote) = explode('://', $cloudId->getRemote(), 2); | |||
$this->remote = $remote; | |||
$this->remoteUser = $remoteUser; | |||
$this->remoteUser = $cloudId->getUser(); | |||
parent::__construct($storage); | |||
} | |||
@@ -47,7 +51,7 @@ class Cache extends \OC\Files\Cache\Cache { | |||
if (!$result) { | |||
return false; | |||
} | |||
$result['displayname_owner'] = $this->remoteUser . '@' . $this->remote; | |||
$result['displayname_owner'] = $this->cloudId->getDisplayId(); | |||
if (!$file || $file === '') { | |||
$result['is_share_mount_point'] = true; | |||
$mountPoint = rtrim($this->storage->getMountPoint()); | |||
@@ -59,7 +63,7 @@ class Cache extends \OC\Files\Cache\Cache { | |||
public function getFolderContentsById($id) { | |||
$results = parent::getFolderContentsById($id); | |||
foreach ($results as &$file) { | |||
$file['displayname_owner'] = $this->remoteUser . '@' . $this->remote; | |||
$file['displayname_owner'] = $this->cloudId->getDisplayId(); | |||
} | |||
return $results; | |||
} |
@@ -22,6 +22,7 @@ | |||
namespace OCA\Files_Sharing\External; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Files\Config\IMountProvider; | |||
use OCP\Files\Storage\IStorageFactory; | |||
use OCP\IDBConnection; | |||
@@ -40,13 +41,20 @@ class MountProvider implements IMountProvider { | |||
*/ | |||
private $managerProvider; | |||
/** | |||
* @var ICloudIdManager | |||
*/ | |||
private $cloudIdManager; | |||
/** | |||
* @param \OCP\IDBConnection $connection | |||
* @param callable $managerProvider due to setup order we need a callable that return the manager instead of the manager itself | |||
* @param ICloudIdManager $cloudIdManager | |||
*/ | |||
public function __construct(IDBConnection $connection, callable $managerProvider) { | |||
public function __construct(IDBConnection $connection, callable $managerProvider, ICloudIdManager $cloudIdManager) { | |||
$this->connection = $connection; | |||
$this->managerProvider = $managerProvider; | |||
$this->cloudIdManager = $cloudIdManager; | |||
} | |||
public function getMount(IUser $user, $data, IStorageFactory $storageFactory) { | |||
@@ -55,6 +63,7 @@ class MountProvider implements IMountProvider { | |||
$data['manager'] = $manager; | |||
$mountPoint = '/' . $user->getUID() . '/files/' . ltrim($data['mountpoint'], '/'); | |||
$data['mountpoint'] = $mountPoint; | |||
$data['cloudId'] = $this->cloudIdManager->getCloudId($data['owner'], $data['remote']); | |||
$data['certificateManager'] = \OC::$server->getCertificateManager($user->getUID()); | |||
$data['HttpClientService'] = \OC::$server->getHTTPClientService(); | |||
return new Mount(self::STORAGE, $mountPoint, $data, $manager, $storageFactory); |
@@ -35,15 +35,14 @@ use OC\ForbiddenException; | |||
use OCA\FederatedFileSharing\DiscoveryManager; | |||
use OCA\Files_Sharing\ISharedStorage; | |||
use OCP\AppFramework\Http; | |||
use OCP\Federation\ICloudId; | |||
use OCP\Files\NotFoundException; | |||
use OCP\Files\StorageInvalidException; | |||
use OCP\Files\StorageNotAvailableException; | |||
class Storage extends DAV implements ISharedStorage { | |||
/** @var string */ | |||
private $remoteUser; | |||
/** @var string */ | |||
private $remote; | |||
/** @var ICloudId */ | |||
private $cloudId; | |||
/** @var string */ | |||
private $mountPoint; | |||
/** @var string */ | |||
@@ -72,9 +71,8 @@ class Storage extends DAV implements ISharedStorage { | |||
$this->manager = $options['manager']; | |||
$this->certificateManager = $options['certificateManager']; | |||
$this->remote = $options['remote']; | |||
$this->remoteUser = $options['owner']; | |||
list($protocol, $remote) = explode('://', $this->remote); | |||
$this->cloudId = $options['cloudId']; | |||
list($protocol, $remote) = explode('://', $this->cloudId->getRemote()); | |||
if (strpos($remote, '/')) { | |||
list($host, $root) = explode('/', $remote, 2); | |||
} else { | |||
@@ -82,7 +80,7 @@ class Storage extends DAV implements ISharedStorage { | |||
$root = ''; | |||
} | |||
$secure = $protocol === 'https'; | |||
$root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->remote); | |||
$root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->cloudId->getRemote()); | |||
$this->mountPoint = $options['mountpoint']; | |||
$this->token = $options['token']; | |||
parent::__construct(array( | |||
@@ -106,11 +104,11 @@ class Storage extends DAV implements ISharedStorage { | |||
} | |||
public function getRemoteUser() { | |||
return $this->remoteUser; | |||
return $this->cloudId->getUser(); | |||
} | |||
public function getRemote() { | |||
return $this->remote; | |||
return $this->cloudId->getRemote(); | |||
} | |||
public function getMountPoint() { | |||
@@ -130,12 +128,12 @@ class Storage extends DAV implements ISharedStorage { | |||
* @return string | |||
*/ | |||
public function getId() { | |||
return 'shared::' . md5($this->token . '@' . $this->remote); | |||
return 'shared::' . md5($this->token . '@' . $this->getRemote()); | |||
} | |||
public function getCache($path = '', $storage = null) { | |||
if (is_null($this->cache)) { | |||
$this->cache = new Cache($this, $this->remote, $this->remoteUser); | |||
$this->cache = new Cache($this, $this->cloudId); | |||
} | |||
return $this->cache; | |||
} | |||
@@ -251,9 +249,9 @@ class Storage extends DAV implements ISharedStorage { | |||
*/ | |||
protected function testRemote() { | |||
try { | |||
return $this->testRemoteUrl($this->remote . '/ocs-provider/index.php') | |||
|| $this->testRemoteUrl($this->remote . '/ocs-provider/') | |||
|| $this->testRemoteUrl($this->remote . '/status.php'); | |||
return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php') | |||
|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/') | |||
|| $this->testRemoteUrl($this->getRemote() . '/status.php'); | |||
} catch (\Exception $e) { | |||
return false; | |||
} | |||
@@ -343,8 +341,7 @@ class Storage extends DAV implements ISharedStorage { | |||
} | |||
public function getOwner($path) { | |||
list(, $remote) = explode('://', $this->remote, 2); | |||
return $this->remoteUser . '@' . $remote; | |||
return $this->cloudId->getDisplayId(); | |||
} | |||
public function isSharable($path) { |
@@ -25,10 +25,12 @@ | |||
namespace OCA\Files_Sharing\Tests\Controller; | |||
use OC\Federation\CloudIdManager; | |||
use OCA\Files_Sharing\Controller\ShareesAPIController; | |||
use OCA\Files_Sharing\Tests\TestCase; | |||
use OCP\AppFramework\Http; | |||
use OCP\AppFramework\OCS\OCSBadRequestException; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\Share; | |||
@@ -64,6 +66,9 @@ class ShareesAPIControllerTest extends TestCase { | |||
/** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */ | |||
private $clientService; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
protected function setUp() { | |||
parent::setUp(); | |||
@@ -93,6 +98,8 @@ class ShareesAPIControllerTest extends TestCase { | |||
$this->clientService = $this->createMock(IClientService::class); | |||
$this->cloudIdManager = new CloudIdManager(); | |||
$this->sharees = new ShareesAPIController( | |||
'files_sharing', | |||
$this->request, | |||
@@ -104,7 +111,8 @@ class ShareesAPIControllerTest extends TestCase { | |||
$this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), | |||
$this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), | |||
$this->shareManager, | |||
$this->clientService | |||
$this->clientService, | |||
$this->cloudIdManager | |||
); | |||
} | |||
@@ -1434,7 +1442,8 @@ class ShareesAPIControllerTest extends TestCase { | |||
$this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), | |||
$this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), | |||
$this->shareManager, | |||
$this->clientService | |||
$this->clientService, | |||
$this->cloudIdManager | |||
]) | |||
->setMethods(array('searchSharees', 'isRemoteSharingAllowed', 'shareProviderExists')) | |||
->getMock(); | |||
@@ -1526,7 +1535,8 @@ class ShareesAPIControllerTest extends TestCase { | |||
$this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), | |||
$this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), | |||
$this->shareManager, | |||
$this->clientService | |||
$this->clientService, | |||
$this->cloudIdManager | |||
]) | |||
->setMethods(array('searchSharees', 'isRemoteSharingAllowed')) | |||
->getMock(); | |||
@@ -1692,7 +1702,8 @@ class ShareesAPIControllerTest extends TestCase { | |||
$this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), | |||
$this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), | |||
$this->shareManager, | |||
$this->clientService | |||
$this->clientService, | |||
$this->cloudIdManager | |||
]) | |||
->setMethods(array('getShareesForShareIds', 'getUsers', 'getGroups', 'getRemote')) | |||
->getMock(); |
@@ -24,7 +24,9 @@ | |||
*/ | |||
namespace OCA\Files_Sharing\Tests\External; | |||
use OC\Federation\CloudIdManager; | |||
use OCA\Files_Sharing\Tests\TestCase; | |||
use OCP\Federation\ICloudIdManager; | |||
/** | |||
* Class Cache | |||
@@ -50,9 +52,13 @@ class CacheTest extends TestCase { | |||
*/ | |||
private $remoteUser; | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
protected function setUp() { | |||
parent::setUp(); | |||
$this->cloudIdManager = new CloudIdManager(); | |||
$this->remoteUser = $this->getUniqueID('remoteuser'); | |||
$this->storage = $this->getMockBuilder('\OCA\Files_Sharing\External\Storage') | |||
@@ -64,8 +70,7 @@ class CacheTest extends TestCase { | |||
->will($this->returnValue('dummystorage::')); | |||
$this->cache = new \OCA\Files_Sharing\External\Cache( | |||
$this->storage, | |||
'http://example.com/owncloud', | |||
$this->remoteUser | |||
$this->cloudIdManager->getCloudId($this->remoteUser, 'http://example.com/owncloud') | |||
); | |||
$this->cache->put( | |||
'test.txt', |
@@ -25,6 +25,7 @@ | |||
namespace OCA\Files_Sharing\Tests\External; | |||
use OC\Federation\CloudIdManager; | |||
use OC\Files\Storage\StorageFactory; | |||
use OCA\FederatedFileSharing\DiscoveryManager; | |||
use OCA\Files_Sharing\External\Manager; | |||
@@ -84,7 +85,7 @@ class ManagerTest extends TestCase { | |||
); | |||
$this->testMountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() { | |||
return $this->manager; | |||
}); | |||
}, new CloudIdManager()); | |||
} | |||
private function setupMounts() { |
@@ -25,6 +25,7 @@ | |||
*/ | |||
namespace OCA\Files_Sharing\Tests; | |||
use OC\Federation\CloudId; | |||
use OCP\Http\Client\IClient; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\Http\Client\IResponse; | |||
@@ -90,6 +91,7 @@ class ExternalStorageTest extends \Test\TestCase { | |||
return new TestSharingExternalStorage( | |||
array( | |||
'cloudId' => new CloudId('testOwner@' . $uri, 'testOwner', $uri), | |||
'remote' => $uri, | |||
'owner' => 'testOwner', | |||
'mountpoint' => 'remoteshare', |
@@ -98,6 +98,8 @@ return array( | |||
'OCP\\Encryption\\IFile' => $baseDir . '/lib/public/Encryption/IFile.php', | |||
'OCP\\Encryption\\IManager' => $baseDir . '/lib/public/Encryption/IManager.php', | |||
'OCP\\Encryption\\Keys\\IStorage' => $baseDir . '/lib/public/Encryption/Keys/IStorage.php', | |||
'OCP\\Federation\\ICloudId' => $baseDir . '/lib/public/Federation/ICloudId.php', | |||
'OCP\\Federation\\ICloudIdManager' => $baseDir . '/lib/public/Federation/ICloudIdManager.php', | |||
'OCP\\Files' => $baseDir . '/lib/public/Files.php', | |||
'OCP\\Files\\AlreadyExistsException' => $baseDir . '/lib/public/Files/AlreadyExistsException.php', | |||
'OCP\\Files\\Cache\\ICache' => $baseDir . '/lib/public/Files/Cache/ICache.php', | |||
@@ -497,6 +499,8 @@ return array( | |||
'OC\\Encryption\\Manager' => $baseDir . '/lib/private/Encryption/Manager.php', | |||
'OC\\Encryption\\Update' => $baseDir . '/lib/private/Encryption/Update.php', | |||
'OC\\Encryption\\Util' => $baseDir . '/lib/private/Encryption/Util.php', | |||
'OC\\Federation\\CloudId' => $baseDir . '/lib/private/Federation/CloudId.php', | |||
'OC\\Federation\\CloudIdManager' => $baseDir . '/lib/private/Federation/CloudIdManager.php', | |||
'OC\\Files\\AppData\\AppData' => $baseDir . '/lib/private/Files/AppData/AppData.php', | |||
'OC\\Files\\AppData\\Factory' => $baseDir . '/lib/private/Files/AppData/Factory.php', | |||
'OC\\Files\\Cache\\Cache' => $baseDir . '/lib/private/Files/Cache/Cache.php', |
@@ -128,6 +128,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c | |||
'OCP\\Encryption\\IFile' => __DIR__ . '/../../..' . '/lib/public/Encryption/IFile.php', | |||
'OCP\\Encryption\\IManager' => __DIR__ . '/../../..' . '/lib/public/Encryption/IManager.php', | |||
'OCP\\Encryption\\Keys\\IStorage' => __DIR__ . '/../../..' . '/lib/public/Encryption/Keys/IStorage.php', | |||
'OCP\\Federation\\ICloudId' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudId.php', | |||
'OCP\\Federation\\ICloudIdManager' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudIdManager.php', | |||
'OCP\\Files' => __DIR__ . '/../../..' . '/lib/public/Files.php', | |||
'OCP\\Files\\AlreadyExistsException' => __DIR__ . '/../../..' . '/lib/public/Files/AlreadyExistsException.php', | |||
'OCP\\Files\\Cache\\ICache' => __DIR__ . '/../../..' . '/lib/public/Files/Cache/ICache.php', | |||
@@ -527,6 +529,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c | |||
'OC\\Encryption\\Manager' => __DIR__ . '/../../..' . '/lib/private/Encryption/Manager.php', | |||
'OC\\Encryption\\Update' => __DIR__ . '/../../..' . '/lib/private/Encryption/Update.php', | |||
'OC\\Encryption\\Util' => __DIR__ . '/../../..' . '/lib/private/Encryption/Util.php', | |||
'OC\\Federation\\CloudId' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudId.php', | |||
'OC\\Federation\\CloudIdManager' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudIdManager.php', | |||
'OC\\Files\\AppData\\AppData' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/AppData.php', | |||
'OC\\Files\\AppData\\Factory' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/Factory.php', | |||
'OC\\Files\\Cache\\Cache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Cache.php', |
@@ -0,0 +1,74 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl> | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OC\Federation; | |||
use OCP\Federation\ICloudId; | |||
class CloudId implements ICloudId { | |||
/** @var string */ | |||
private $id; | |||
/** @var string */ | |||
private $user; | |||
/** @var string */ | |||
private $remote; | |||
/** | |||
* CloudId constructor. | |||
* | |||
* @param string $id | |||
* @param string $user | |||
* @param string $remote | |||
*/ | |||
public function __construct($id, $user, $remote) { | |||
$this->id = $id; | |||
$this->user = $user; | |||
$this->remote = $remote; | |||
} | |||
/** | |||
* The full remote cloud id | |||
* | |||
* @return string | |||
*/ | |||
public function getId() { | |||
return $this->id; | |||
} | |||
public function getDisplayId() { | |||
return str_replace('https://', '', str_replace('http://', '', $this->getId())); | |||
} | |||
/** | |||
* The username on the remote server | |||
* | |||
* @return string | |||
*/ | |||
public function getUser() { | |||
return $this->user; | |||
} | |||
/** | |||
* The base address of the remote server | |||
* | |||
* @return string | |||
*/ | |||
public function getRemote() { | |||
return $this->remote; | |||
} | |||
} |
@@ -0,0 +1,108 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl> | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OC\Federation; | |||
use OCP\Federation\ICloudId; | |||
use OCP\Federation\ICloudIdManager; | |||
class CloudIdManager implements ICloudIdManager { | |||
/** | |||
* @param string $cloudId | |||
* @return ICloudId | |||
*/ | |||
public function resolveCloudId($cloudId) { | |||
// TODO magic here to get the url and user instead of just splitting on @ | |||
if (!$this->isValidCloudId($cloudId)) { | |||
throw new \InvalidArgumentException('Invalid cloud id'); | |||
} | |||
// Find the first character that is not allowed in user names | |||
$id = str_replace('\\', '/', $cloudId); | |||
$posSlash = strpos($id, '/'); | |||
$posColon = strpos($id, ':'); | |||
if ($posSlash === false && $posColon === false) { | |||
$invalidPos = strlen($id); | |||
} else if ($posSlash === false) { | |||
$invalidPos = $posColon; | |||
} else if ($posColon === false) { | |||
$invalidPos = $posSlash; | |||
} else { | |||
$invalidPos = min($posSlash, $posColon); | |||
} | |||
// Find the last @ before $invalidPos | |||
$pos = $lastAtPos = 0; | |||
while ($lastAtPos !== false && $lastAtPos <= $invalidPos) { | |||
$pos = $lastAtPos; | |||
$lastAtPos = strpos($id, '@', $pos + 1); | |||
} | |||
if ($pos !== false) { | |||
$user = substr($id, 0, $pos); | |||
$remote = substr($id, $pos + 1); | |||
$remote = $this->fixRemoteURL($remote); | |||
if (!empty($user) && !empty($remote)) { | |||
return new CloudId($cloudId, $user, $remote); | |||
} | |||
} | |||
throw new \InvalidArgumentException('Invalid cloud id'); | |||
} | |||
/** | |||
* @param string $user | |||
* @param string $remote | |||
* @return CloudId | |||
*/ | |||
public function getCloudId($user, $remote) { | |||
// TODO check what the correct url is for remote (asking the remote) | |||
return new CloudId($user. '@' . $remote, $user, $remote); | |||
} | |||
/** | |||
* Strips away a potential file names and trailing slashes: | |||
* - http://localhost | |||
* - http://localhost/ | |||
* - http://localhost/index.php | |||
* - http://localhost/index.php/s/{shareToken} | |||
* | |||
* all return: http://localhost | |||
* | |||
* @param string $remote | |||
* @return string | |||
*/ | |||
protected function fixRemoteURL($remote) { | |||
$remote = str_replace('\\', '/', $remote); | |||
if ($fileNamePosition = strpos($remote, '/index.php')) { | |||
$remote = substr($remote, 0, $fileNamePosition); | |||
} | |||
$remote = rtrim($remote, '/'); | |||
return $remote; | |||
} | |||
/** | |||
* @param string $cloudId | |||
* @return bool | |||
*/ | |||
public function isValidCloudId($cloudId) { | |||
return strpos($cloudId, '@') !== false; | |||
} | |||
} |
@@ -52,6 +52,7 @@ use OC\Diagnostics\EventLogger; | |||
use OC\Diagnostics\NullEventLogger; | |||
use OC\Diagnostics\NullQueryLogger; | |||
use OC\Diagnostics\QueryLogger; | |||
use OC\Federation\CloudIdManager; | |||
use OC\Files\Config\UserMountCache; | |||
use OC\Files\Config\UserMountCacheListener; | |||
use OC\Files\Mount\CacheMountProvider; | |||
@@ -90,6 +91,7 @@ use OC\Security\TrustedDomainHelper; | |||
use OC\Session\CryptoWrapper; | |||
use OC\Tagging\TagMapper; | |||
use OCA\Theming\ThemingDefaults; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Authentication\LoginCredentials\IStore; | |||
use OCP\IL10N; | |||
use OCP\IServerContainer; | |||
@@ -825,6 +827,10 @@ class Server extends ServerContainer implements IServerContainer { | |||
return new LockdownManager(); | |||
}); | |||
$this->registerService(ICloudIdManager::class, function (Server $c) { | |||
return new CloudIdManager(); | |||
}); | |||
/* To trick DI since we don't extend the DIContainer here */ | |||
$this->registerService(CleanPreviewsBackgroundJob::class, function (Server $c) { | |||
return new CleanPreviewsBackgroundJob( | |||
@@ -1570,4 +1576,11 @@ class Server extends ServerContainer implements IServerContainer { | |||
public function getLockdownManager() { | |||
return $this->query('LockdownManager'); | |||
} | |||
/** | |||
* @return \OCP\Federation\ICloudIdManager | |||
*/ | |||
public function getCloudIdManager() { | |||
return $this->query(ICloudIdManager::class); | |||
} | |||
} |
@@ -249,46 +249,14 @@ class Helper extends \OC\Share\Constants { | |||
* @throws HintException | |||
*/ | |||
public static function splitUserRemote($id) { | |||
if (strpos($id, '@') === false) { | |||
try { | |||
$cloudId = \OC::$server->getCloudIdManager()->resolveCloudId($id); | |||
return [$cloudId->getUser(), $cloudId->getRemote()]; | |||
} catch (\InvalidArgumentException $e) { | |||
$l = \OC::$server->getL10N('core'); | |||
$hint = $l->t('Invalid Federated Cloud ID'); | |||
throw new HintException('Invalid Federated Cloud ID', $hint); | |||
throw new HintException('Invalid Federated Cloud ID', $hint, 0, $e); | |||
} | |||
// Find the first character that is not allowed in user names | |||
$id = str_replace('\\', '/', $id); | |||
$posSlash = strpos($id, '/'); | |||
$posColon = strpos($id, ':'); | |||
if ($posSlash === false && $posColon === false) { | |||
$invalidPos = strlen($id); | |||
} else if ($posSlash === false) { | |||
$invalidPos = $posColon; | |||
} else if ($posColon === false) { | |||
$invalidPos = $posSlash; | |||
} else { | |||
$invalidPos = min($posSlash, $posColon); | |||
} | |||
// Find the last @ before $invalidPos | |||
$pos = $lastAtPos = 0; | |||
while ($lastAtPos !== false && $lastAtPos <= $invalidPos) { | |||
$pos = $lastAtPos; | |||
$lastAtPos = strpos($id, '@', $pos + 1); | |||
} | |||
if ($pos !== false) { | |||
$user = substr($id, 0, $pos); | |||
$remote = substr($id, $pos + 1); | |||
$remote = self::fixRemoteURL($remote); | |||
if (!empty($user) && !empty($remote)) { | |||
return array($user, $remote); | |||
} | |||
} | |||
$l = \OC::$server->getL10N('core'); | |||
$hint = $l->t('Invalid Federated Cloud ID'); | |||
throw new HintException('Invalid Fededrated Cloud ID', $hint); | |||
} | |||
/** |
@@ -96,7 +96,8 @@ class ProviderFactory implements IProviderFactory { | |||
$l = $this->serverContainer->getL10N('federatedfilessharing'); | |||
$addressHandler = new AddressHandler( | |||
$this->serverContainer->getURLGenerator(), | |||
$l | |||
$l, | |||
$this->serverContainer->getCloudIdManager() | |||
); | |||
$discoveryManager = new DiscoveryManager( | |||
$this->serverContainer->getMemCacheFactory(), | |||
@@ -121,7 +122,8 @@ class ProviderFactory implements IProviderFactory { | |||
$this->serverContainer->getLogger(), | |||
$this->serverContainer->getLazyRootFolder(), | |||
$this->serverContainer->getConfig(), | |||
$this->serverContainer->getUserManager() | |||
$this->serverContainer->getUserManager(), | |||
$this->serverContainer->getCloudIdManager() | |||
); | |||
} | |||
@@ -411,7 +411,8 @@ class User implements IUser { | |||
public function getCloudId() { | |||
$uid = $this->getUID(); | |||
$server = $this->urlGenerator->getAbsoluteURL('/'); | |||
return $uid . '@' . rtrim( $this->removeProtocolFromUrl($server), '/'); | |||
$server = rtrim( $this->removeProtocolFromUrl($server), '/'); | |||
return \OC::$server->getCloudIdManager()->getCloudId($uid, $server)->getId(); | |||
} | |||
/** |
@@ -0,0 +1,58 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl> | |||
* | |||
* 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 OCP\Federation; | |||
/** | |||
* Parsed federated cloud id | |||
* | |||
* @since 12.0.0 | |||
*/ | |||
interface ICloudId { | |||
/** | |||
* The remote cloud id | |||
* | |||
* @return string | |||
* @since 12.0.0 | |||
*/ | |||
public function getId(); | |||
/** | |||
* Get a clean representation of the cloud id for display | |||
* | |||
* @return string | |||
* @since 12.0.0 | |||
*/ | |||
public function getDisplayId(); | |||
/** | |||
* The username on the remote server | |||
* | |||
* @return string | |||
* @since 12.0.0 | |||
*/ | |||
public function getUser(); | |||
/** | |||
* The base address of the remote server | |||
* | |||
* @return string | |||
* @since 12.0.0 | |||
*/ | |||
public function getRemote(); | |||
} |
@@ -0,0 +1,55 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl> | |||
* | |||
* 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 OCP\Federation; | |||
/** | |||
* Interface for resolving federated cloud ids | |||
* | |||
* @since 12.0.0 | |||
*/ | |||
interface ICloudIdManager { | |||
/** | |||
* @param string $cloudId | |||
* @return ICloudId | |||
* | |||
* @since 12.0.0 | |||
*/ | |||
public function resolveCloudId($cloudId); | |||
/** | |||
* Get the cloud id for a remote user | |||
* | |||
* @param string $user | |||
* @param string $remote | |||
* @return ICloudId | |||
* | |||
* @since 12.0.0 | |||
*/ | |||
public function getCloudId($user, $remote); | |||
/** | |||
* Check if the input is a correctly formatted cloud id | |||
* | |||
* @param string $cloudId | |||
* @return bool | |||
* | |||
* @since 12.0.0 | |||
*/ | |||
public function isValidCloudId($cloudId); | |||
} |
@@ -525,4 +525,10 @@ interface IServerContainer { | |||
* @since 8.0.0 | |||
*/ | |||
public function getDateTimeFormatter(); | |||
/** | |||
* @return \OCP\Federation\ICloudIdManager | |||
* @since 12.0.0 | |||
*/ | |||
public function getCloudIdManager(); | |||
} |