diff options
author | Robin Appelman <robin@icewind.nl> | 2017-02-09 14:54:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-09 14:54:32 +0100 |
commit | bf88060a98ce397768d4afa7935b80751e4533f8 (patch) | |
tree | 6baaf10832fa68999eea01ab3df5241fdd3ece0a /lib/private | |
parent | 4a5a3681d921adad8c4cb5bb29180514446ea2b9 (diff) | |
parent | 0d8d658b7e3885d92103a6e6248b37863f9acf1b (diff) | |
download | nextcloud-server-bf88060a98ce397768d4afa7935b80751e4533f8.tar.gz nextcloud-server-bf88060a98ce397768d4afa7935b80751e4533f8.zip |
Merge pull request #3297 from nextcloud/cloud-id-resolve
Add a single public api for resolving a cloud id to a user and remote and back
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Federation/CloudId.php | 76 | ||||
-rw-r--r-- | lib/private/Federation/CloudIdManager.php | 109 | ||||
-rw-r--r-- | lib/private/Server.php | 13 | ||||
-rw-r--r-- | lib/private/Share/Helper.php | 42 | ||||
-rw-r--r-- | lib/private/Share20/ProviderFactory.php | 6 | ||||
-rw-r--r-- | lib/private/User/User.php | 3 |
6 files changed, 209 insertions, 40 deletions
diff --git a/lib/private/Federation/CloudId.php b/lib/private/Federation/CloudId.php new file mode 100644 index 00000000000..6ba4ff9166b --- /dev/null +++ b/lib/private/Federation/CloudId.php @@ -0,0 +1,76 @@ +<?php +/** + * @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * 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; + } +} diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php new file mode 100644 index 00000000000..45cc69b306e --- /dev/null +++ b/lib/private/Federation/CloudIdManager.php @@ -0,0 +1,109 @@ +<?php +/** + * @copyright Copyright (c) 2017, Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * 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 = $this->fixRemoteURL($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); + if (!empty($user) && !empty($remote)) { + return new CloudId($id, $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; + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 3c716ae6ce6..bcbe23b0181 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -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); + } } diff --git a/lib/private/Share/Helper.php b/lib/private/Share/Helper.php index 20aaa793728..a1a56077d40 100644 --- a/lib/private/Share/Helper.php +++ b/lib/private/Share/Helper.php @@ -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); } /** diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 3f277a852b3..87d9d221810 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -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() ); } diff --git a/lib/private/User/User.php b/lib/private/User/User.php index c37bb59028e..961f70f8a8e 100644 --- a/lib/private/User/User.php +++ b/lib/private/User/User.php @@ -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(); } /** |