diff options
author | Robin Appelman <robin@icewind.nl> | 2017-01-27 12:52:17 +0100 |
---|---|---|
committer | Robin Appelman <robin@icewind.nl> | 2017-02-08 15:17:02 +0100 |
commit | fa49c4a13b6c5455b13ad44cfc158b271aa9b616 (patch) | |
tree | 1014b6de1bd3761e2e26467c78c6f5fd4697ea56 /lib | |
parent | 1a591cea97313b8500154d6c2c9ce3aaf2f38a88 (diff) | |
download | nextcloud-server-fa49c4a13b6c5455b13ad44cfc158b271aa9b616.tar.gz nextcloud-server-fa49c4a13b6c5455b13ad44cfc158b271aa9b616.zip |
Add a single public api for resolving a cloud id to a user and remote and back
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 4 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 4 | ||||
-rw-r--r-- | lib/private/Federation/CloudId.php | 74 | ||||
-rw-r--r-- | lib/private/Federation/CloudIdManager.php | 108 | ||||
-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 | ||||
-rw-r--r-- | lib/public/Federation/ICloudId.php | 58 | ||||
-rw-r--r-- | lib/public/Federation/ICloudIdManager.php | 55 | ||||
-rw-r--r-- | lib/public/IServerContainer.php | 6 |
11 files changed, 333 insertions, 40 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 4a345ed7a6d..5bd9da04072 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -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', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index f8d360fec4b..475b4c15542 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.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', diff --git a/lib/private/Federation/CloudId.php b/lib/private/Federation/CloudId.php new file mode 100644 index 00000000000..746bd2eaf71 --- /dev/null +++ b/lib/private/Federation/CloudId.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; + } +}
\ No newline at end of file diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php new file mode 100644 index 00000000000..d5d4e7f34cc --- /dev/null +++ b/lib/private/Federation/CloudIdManager.php @@ -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; + } +}
\ No newline at end of file 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(); } /** diff --git a/lib/public/Federation/ICloudId.php b/lib/public/Federation/ICloudId.php new file mode 100644 index 00000000000..0985544fee8 --- /dev/null +++ b/lib/public/Federation/ICloudId.php @@ -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(); +}
\ No newline at end of file diff --git a/lib/public/Federation/ICloudIdManager.php b/lib/public/Federation/ICloudIdManager.php new file mode 100644 index 00000000000..a81a4af6186 --- /dev/null +++ b/lib/public/Federation/ICloudIdManager.php @@ -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); +}
\ No newline at end of file diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php index 87628be01f7..02a092ea660 100644 --- a/lib/public/IServerContainer.php +++ b/lib/public/IServerContainer.php @@ -525,4 +525,10 @@ interface IServerContainer { * @since 8.0.0 */ public function getDateTimeFormatter(); + + /** + * @return \OCP\Federation\ICloudIdManager + * @since 12.0.0 + */ + public function getCloudIdManager(); } |