diff options
84 files changed, 1018 insertions, 409 deletions
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php index f524c47a821..7f2ff2b37da 100644 --- a/apps/dav/appinfo/v1/caldav.php +++ b/apps/dav/appinfo/v1/caldav.php @@ -67,6 +67,7 @@ $nodes = array( // Fire up server $server = new \Sabre\DAV\Server($nodes); +$server::$exposeVersion = false; $server->httpRequest->setUrl(\OC::$server->getRequest()->getRequestUri()); $server->setBaseUri($baseuri); diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php index b70045d420b..04344e83fde 100644 --- a/apps/dav/appinfo/v1/carddav.php +++ b/apps/dav/appinfo/v1/carddav.php @@ -66,6 +66,7 @@ $nodes = array( // Fire up server $server = new \Sabre\DAV\Server($nodes); +$server::$exposeVersion = false; $server->httpRequest->setUrl(\OC::$server->getRequest()->getRequestUri()); $server->setBaseUri($baseuri); // Add plugins diff --git a/apps/dav/l10n/sq.js b/apps/dav/l10n/sq.js index e84a2e2354f..6a683d01712 100644 --- a/apps/dav/l10n/sq.js +++ b/apps/dav/l10n/sq.js @@ -28,9 +28,11 @@ OC.L10N.register( "{actor} created todo {todo} in list {calendar}" : "{actor} u krijua todo{todo} në listën {calendar}", "You created todo {todo} in list {calendar}" : "Ju krijuat todo {todo} në listën {calendar}", "{actor} deleted todo {todo} from list {calendar}" : "{actor} u fshi todo{ todo} nga lista{calendar}", + "You deleted todo {todo} from list {calendar}" : "Ju fshit todo{todo} nga lista {calendar}", "{actor} updated todo {todo} in list {calendar}" : "{actor} u përditësua todo{todo} në listën{calendar}", "A <strong>calendar</strong> was modified" : "Një <strong>kalendar</strong> u modifikua", "A calendar <strong>event</strong> was modified" : "Një <strong>event</strong> në kalendar u modifikua", + "A calendar <strong>todo</strong> was modified" : "Një kalendar <strong>todo<strong> u modifikua", "Personal" : "Personale", "Contacts" : "Kontaktet", "Technical details" : "Detaje teknike", diff --git a/apps/dav/l10n/sq.json b/apps/dav/l10n/sq.json index 922e7122069..f5a98e8845c 100644 --- a/apps/dav/l10n/sq.json +++ b/apps/dav/l10n/sq.json @@ -26,9 +26,11 @@ "{actor} created todo {todo} in list {calendar}" : "{actor} u krijua todo{todo} në listën {calendar}", "You created todo {todo} in list {calendar}" : "Ju krijuat todo {todo} në listën {calendar}", "{actor} deleted todo {todo} from list {calendar}" : "{actor} u fshi todo{ todo} nga lista{calendar}", + "You deleted todo {todo} from list {calendar}" : "Ju fshit todo{todo} nga lista {calendar}", "{actor} updated todo {todo} in list {calendar}" : "{actor} u përditësua todo{todo} në listën{calendar}", "A <strong>calendar</strong> was modified" : "Një <strong>kalendar</strong> u modifikua", "A calendar <strong>event</strong> was modified" : "Një <strong>event</strong> në kalendar u modifikua", + "A calendar <strong>todo</strong> was modified" : "Një kalendar <strong>todo<strong> u modifikua", "Personal" : "Personale", "Contacts" : "Kontaktet", "Technical details" : "Detaje teknike", diff --git a/apps/dav/lib/Connector/LegacyDAVACL.php b/apps/dav/lib/Connector/LegacyDAVACL.php index d5185ecd03b..46cbb504cce 100644 --- a/apps/dav/lib/Connector/LegacyDAVACL.php +++ b/apps/dav/lib/Connector/LegacyDAVACL.php @@ -67,6 +67,7 @@ class LegacyDAVACL extends DavAclPlugin { return new Principal(Principal::UNAUTHENTICATED); } }); - parent::propFind($propFind, $node); + + return parent::propFind($propFind, $node); } } diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php index 95222dafec9..93d8b14d9c9 100644 --- a/apps/dav/lib/Connector/Sabre/Auth.php +++ b/apps/dav/lib/Connector/Sabre/Auth.php @@ -32,7 +32,6 @@ namespace OCA\DAV\Connector\Sabre; use Exception; -use OC\AppFramework\Http\Request; use OC\Authentication\Exceptions\PasswordLoginForbiddenException; use OC\Authentication\TwoFactorAuth\Manager; use OC\Security\Bruteforce\Throttler; @@ -177,9 +176,9 @@ class Auth extends AbstractBasic { // Official ownCloud clients require no checks if($this->request->isUserAgent([ - Request::USER_AGENT_OWNCLOUD_DESKTOP, - Request::USER_AGENT_OWNCLOUD_ANDROID, - Request::USER_AGENT_OWNCLOUD_IOS, + IRequest::USER_AGENT_CLIENT_DESKTOP, + IRequest::USER_AGENT_CLIENT_ANDROID, + IRequest::USER_AGENT_CLIENT_IOS, ])) { return false; } diff --git a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php index 244394ec6fc..427a3756019 100644 --- a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php +++ b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php @@ -23,6 +23,7 @@ namespace OCA\DAV\Connector\Sabre; +use Sabre\CalDAV\Principal\User; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\IFile; use Sabre\DAV\INode; @@ -72,4 +73,20 @@ class DavAclPlugin extends \Sabre\DAVACL\Plugin { return $access; } + + public function propFind(PropFind $propFind, INode $node) { + // If the node is neither readable nor writable then fail unless its of + // the standard user-principal + if(!($node instanceof User)) { + $path = $propFind->getPath(); + $readPermissions = $this->checkPrivileges($path, '{DAV:}read', self::R_PARENT, false); + $writePermissions = $this->checkPrivileges($path, '{DAV:}write', self::R_PARENT, false); + if ($readPermissions === false && $writePermissions === false) { + $this->checkPrivileges($path, '{DAV:}read', self::R_PARENT, true); + $this->checkPrivileges($path, '{DAV:}write', self::R_PARENT, true); + } + } + + return parent::propFind($propFind, $node); + } } diff --git a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php index 74b85b8a1c9..dfcb7939799 100644 --- a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php @@ -302,7 +302,7 @@ class AuthTest extends TestCase { ->with([ '/^Mozilla\/5\.0 \([A-Za-z ]+\) (mirall|csyncoC)\/.*$/', '/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/', - '/^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/', + '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/', ]) ->willReturn(false); $this->session @@ -352,7 +352,7 @@ class AuthTest extends TestCase { ->with([ '/^Mozilla\/5\.0 \([A-Za-z ]+\) (mirall|csyncoC)\/.*$/', '/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/', - '/^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/', + '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/', ]) ->willReturn(false); $this->session @@ -406,7 +406,7 @@ class AuthTest extends TestCase { ->with([ '/^Mozilla\/5\.0 \([A-Za-z ]+\) (mirall|csyncoC)\/.*$/', '/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/', - '/^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/', + '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/', ]) ->willReturn(false); $this->session @@ -452,7 +452,7 @@ class AuthTest extends TestCase { ->with([ '/^Mozilla\/5\.0 \([A-Za-z ]+\) (mirall|csyncoC)\/.*$/', '/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/', - '/^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/', + '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/', ]) ->willReturn(true); $this->session diff --git a/apps/federatedfilesharing/l10n/sq.js b/apps/federatedfilesharing/l10n/sq.js index 4e55e171b81..a12e4470755 100644 --- a/apps/federatedfilesharing/l10n/sq.js +++ b/apps/federatedfilesharing/l10n/sq.js @@ -13,6 +13,7 @@ OC.L10N.register( "Press Ctrl-C to copy." : "Shtypni Ctrl-C për të kopjuar", "Invalid Federated Cloud ID" : "ID Federated Cloud e pavlefshme", "Server to server sharing is not enabled on this server" : "Shpërndarja server në server nuk është e mundësuar në këtë server", + "Invalid or untrusted SSL certificate" : "Çertifikatë SSL e pavlefshme ose e dyshimtë", "Storage not valid" : "memorja nuk është e vlefshme", "Couldn't add remote share" : "Nuk mund të shtohet ndarja në largësi", "Sharing %s failed, because this item is already shared with %s" : "Ndarja për %s dështoi, ngaqë ky objekt është ndarë një herë me %s", diff --git a/apps/federatedfilesharing/l10n/sq.json b/apps/federatedfilesharing/l10n/sq.json index 07858aa6434..b255001bd7f 100644 --- a/apps/federatedfilesharing/l10n/sq.json +++ b/apps/federatedfilesharing/l10n/sq.json @@ -11,6 +11,7 @@ "Press Ctrl-C to copy." : "Shtypni Ctrl-C për të kopjuar", "Invalid Federated Cloud ID" : "ID Federated Cloud e pavlefshme", "Server to server sharing is not enabled on this server" : "Shpërndarja server në server nuk është e mundësuar në këtë server", + "Invalid or untrusted SSL certificate" : "Çertifikatë SSL e pavlefshme ose e dyshimtë", "Storage not valid" : "memorja nuk është e vlefshme", "Couldn't add remote share" : "Nuk mund të shtohet ndarja në largësi", "Sharing %s failed, because this item is already shared with %s" : "Ndarja për %s dështoi, ngaqë ky objekt është ndarë një herë me %s", diff --git a/apps/federatedfilesharing/lib/AddressHandler.php b/apps/federatedfilesharing/lib/AddressHandler.php index 5fc41c2c804..6c59df06863 100644 --- a/apps/federatedfilesharing/lib/AddressHandler.php +++ b/apps/federatedfilesharing/lib/AddressHandler.php @@ -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; - } - } diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php index c37cb9b87bb..3e97edeada0 100644 --- a/apps/federatedfilesharing/lib/AppInfo/Application.php +++ b/apps/federatedfilesharing/lib/AppInfo/Application.php @@ -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() ); } diff --git a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php index 26afcae32b7..2356c569d87 100644 --- a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php +++ b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php @@ -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(), diff --git a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php index 3c399268124..dd2e88d2dae 100644 --- a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php +++ b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php @@ -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, diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php index 750415077a8..a5e75e145c8 100644 --- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php +++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php @@ -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']; diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php index 61f1b1c8f18..fb49978b7af 100644 --- a/apps/federatedfilesharing/lib/FederatedShareProvider.php +++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php @@ -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($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 ); diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php index 507dd98330e..faf79480b7e 100644 --- a/apps/federatedfilesharing/lib/Notifier.php +++ b/apps/federatedfilesharing/lib/Notifier.php @@ -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(); } /** diff --git a/apps/federatedfilesharing/tests/AddressHandlerTest.php b/apps/federatedfilesharing/tests/AddressHandlerTest.php index f62f3b62e03..6d215d40156 100644 --- a/apps/federatedfilesharing/tests/AddressHandlerTest.php +++ b/apps/federatedfilesharing/tests/AddressHandlerTest.php @@ -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() { @@ -196,26 +202,4 @@ class AddressHandlerTest extends \Test\TestCase { ['httpserver.com', false], ]; } - - /** - * @dataProvider dataTestFixRemoteUrl - * - * @param string $url - * @param string $expected - */ - public function testFixRemoteUrl($url, $expected) { - $this->assertSame($expected, - $this->invokePrivate($this->addressHandler, 'fixRemoteURL', [$url]) - ); - } - - public function dataTestFixRemoteUrl() { - return [ - ['http://localhost', 'http://localhost'], - ['http://localhost/', 'http://localhost'], - ['http://localhost/index.php', 'http://localhost'], - ['http://localhost/index.php/s/AShareToken', 'http://localhost'], - ]; - } - } diff --git a/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php b/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php index bd091bed410..7714ff4731c 100644 --- a/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php +++ b/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php @@ -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 ); } diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php index 18d698d398e..61f87e9ec67 100644 --- a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php +++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php @@ -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(); diff --git a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php index 874d4b48a5c..97d8ccd65c3 100644 --- a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php +++ b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php @@ -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(); diff --git a/apps/files/lib/Activity/FavoriteProvider.php b/apps/files/lib/Activity/FavoriteProvider.php index ed00d50f221..941579e730d 100644 --- a/apps/files/lib/Activity/FavoriteProvider.php +++ b/apps/files/lib/Activity/FavoriteProvider.php @@ -138,12 +138,21 @@ class FavoriteProvider implements IProvider { * @param string $subject */ protected function setSubjects(IEvent $event, $subject) { + $subjectParams = $event->getSubjectParameters(); + if (empty($subjectParams)) { + // Try to fall back to the old way, but this does not work for emails. + // But at least old activities still work. + $subjectParams = [ + 'id' => $event->getObjectId(), + 'path' => $event->getObjectName(), + ]; + } $parameter = [ 'type' => 'file', - 'id' => $event->getObjectId(), - 'name' => basename($event->getObjectName()), - 'path' => trim($event->getObjectName(), '/'), - 'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $event->getObjectId()]), + 'id' => $subjectParams['id'], + 'name' => basename($subjectParams['path']), + 'path' => trim($subjectParams['path'], '/'), + 'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $subjectParams['id']]), ]; $event->setParsedSubject(str_replace('{file}', $parameter['path'], $subject)) diff --git a/apps/files/lib/Service/TagService.php b/apps/files/lib/Service/TagService.php index cf80d780eaf..cea26d26d16 100644 --- a/apps/files/lib/Service/TagService.php +++ b/apps/files/lib/Service/TagService.php @@ -116,14 +116,21 @@ class TagService { } $event = $this->activityManager->generateEvent(); - $event->setApp('files') - ->setObject('files', $fileId, $path) - ->setType('favorite') - ->setAuthor($user->getUID()) - ->setAffectedUser($user->getUID()) - ->setTimestamp(time()) - ->setSubject($addToFavorite ? FavoriteProvider::SUBJECT_ADDED : FavoriteProvider::SUBJECT_REMOVED); - $this->activityManager->publish($event); + try { + $event->setApp('files') + ->setObject('files', $fileId, $path) + ->setType('favorite') + ->setAuthor($user->getUID()) + ->setAffectedUser($user->getUID()) + ->setTimestamp(time()) + ->setSubject( + $addToFavorite ? FavoriteProvider::SUBJECT_ADDED : FavoriteProvider::SUBJECT_REMOVED, + ['id' => $fileId, 'path' => $path] + ); + $this->activityManager->publish($event); + } catch (\InvalidArgumentException $e) { + } catch (\BadMethodCallException $e) { + } } } diff --git a/apps/files_sharing/l10n/de.js b/apps/files_sharing/l10n/de.js index 17b76d788ee..edd9d757be9 100644 --- a/apps/files_sharing/l10n/de.js +++ b/apps/files_sharing/l10n/de.js @@ -36,10 +36,13 @@ OC.L10N.register( "Public link expired" : "öffentlicher Link ist abgelaufen", "{actor} shared as public link" : "{actor} hat einen öffentlichen Link geteilt", "{actor} removed public link" : "{actor} hat einen öffentlichen Link entfernt", + "Public link of {actor} expired" : "Öffentlicher Link von {actor} ist abgelaufen", "You shared {file} as public link" : "Du hast {file} über einen öffentlichen Link geteilt", "You removed public link for {file}" : "Du hast die öffentliche Freigabe für {file} entfernt", + "Public link expired for {file}" : "Öffentlicher Link für {file} ist abgelaufen", "{actor} shared {file} as public link" : "{actor} hat {file} über einen öffentlichen Link geteilt", "{actor} removed public link for {file}" : "{actor} hat einen öffentlichen Link {file} entfernt", + "Public link of {actor} for {file} expired" : "Öffentlicher Link von {actor} für {file} ist abgelaufen", "{user} accepted the remote share" : "{user} hat die Remotefreigabe akzeptiert", "{user} declined the remote share" : "{user} hat die Remotefreigabe abgelehnt", "You received a new remote share {file} from {user}" : "Du hast eine neue Remotefreigabe {file} von {user} erhalten", diff --git a/apps/files_sharing/l10n/de.json b/apps/files_sharing/l10n/de.json index e634290cd45..487722d420d 100644 --- a/apps/files_sharing/l10n/de.json +++ b/apps/files_sharing/l10n/de.json @@ -34,10 +34,13 @@ "Public link expired" : "öffentlicher Link ist abgelaufen", "{actor} shared as public link" : "{actor} hat einen öffentlichen Link geteilt", "{actor} removed public link" : "{actor} hat einen öffentlichen Link entfernt", + "Public link of {actor} expired" : "Öffentlicher Link von {actor} ist abgelaufen", "You shared {file} as public link" : "Du hast {file} über einen öffentlichen Link geteilt", "You removed public link for {file}" : "Du hast die öffentliche Freigabe für {file} entfernt", + "Public link expired for {file}" : "Öffentlicher Link für {file} ist abgelaufen", "{actor} shared {file} as public link" : "{actor} hat {file} über einen öffentlichen Link geteilt", "{actor} removed public link for {file}" : "{actor} hat einen öffentlichen Link {file} entfernt", + "Public link of {actor} for {file} expired" : "Öffentlicher Link von {actor} für {file} ist abgelaufen", "{user} accepted the remote share" : "{user} hat die Remotefreigabe akzeptiert", "{user} declined the remote share" : "{user} hat die Remotefreigabe abgelehnt", "You received a new remote share {file} from {user}" : "Du hast eine neue Remotefreigabe {file} von {user} erhalten", diff --git a/apps/files_sharing/l10n/de_DE.js b/apps/files_sharing/l10n/de_DE.js index 9bb79fe9183..b52fb1e2941 100644 --- a/apps/files_sharing/l10n/de_DE.js +++ b/apps/files_sharing/l10n/de_DE.js @@ -36,10 +36,13 @@ OC.L10N.register( "Public link expired" : "öffentlicher Link ist abgelaufen", "{actor} shared as public link" : "{actor} hat einen öffentlichen Link geteilt", "{actor} removed public link" : "{actor} hat einen öffentlichen Link entfernt", + "Public link of {actor} expired" : "Öffentlicher Link von {actor} ist abgelaufen", "You shared {file} as public link" : "Sie haben {file} über einen öffentlichen Link geteilt", "You removed public link for {file}" : "Sie haben die öffentliche Freigabe für {file} entfernt", + "Public link expired for {file}" : "Öffentlicher Link für {file} ist abgelaufen", "{actor} shared {file} as public link" : "{actor} hat {file} über einen öffentlichen Link geteilt", "{actor} removed public link for {file}" : "{actor} hat einen öffentlichen Link {file} entfernt", + "Public link of {actor} for {file} expired" : "Öffentlicher Link von {actor} für {file} ist abgelaufen", "{user} accepted the remote share" : "{user} hat die Remotefreigabe akzeptiert", "{user} declined the remote share" : "{user} hat die Remotefreigabe abgelehnt", "You received a new remote share {file} from {user}" : "Du hast eine neue Remotefreigabe {file} von {user} erhalten", diff --git a/apps/files_sharing/l10n/de_DE.json b/apps/files_sharing/l10n/de_DE.json index 124928b4449..6870a2b7d4d 100644 --- a/apps/files_sharing/l10n/de_DE.json +++ b/apps/files_sharing/l10n/de_DE.json @@ -34,10 +34,13 @@ "Public link expired" : "öffentlicher Link ist abgelaufen", "{actor} shared as public link" : "{actor} hat einen öffentlichen Link geteilt", "{actor} removed public link" : "{actor} hat einen öffentlichen Link entfernt", + "Public link of {actor} expired" : "Öffentlicher Link von {actor} ist abgelaufen", "You shared {file} as public link" : "Sie haben {file} über einen öffentlichen Link geteilt", "You removed public link for {file}" : "Sie haben die öffentliche Freigabe für {file} entfernt", + "Public link expired for {file}" : "Öffentlicher Link für {file} ist abgelaufen", "{actor} shared {file} as public link" : "{actor} hat {file} über einen öffentlichen Link geteilt", "{actor} removed public link for {file}" : "{actor} hat einen öffentlichen Link {file} entfernt", + "Public link of {actor} for {file} expired" : "Öffentlicher Link von {actor} für {file} ist abgelaufen", "{user} accepted the remote share" : "{user} hat die Remotefreigabe akzeptiert", "{user} declined the remote share" : "{user} hat die Remotefreigabe abgelehnt", "You received a new remote share {file} from {user}" : "Du hast eine neue Remotefreigabe {file} von {user} erhalten", diff --git a/apps/files_sharing/l10n/es.js b/apps/files_sharing/l10n/es.js index 81a6a1d6fce..40bdeafee29 100644 --- a/apps/files_sharing/l10n/es.js +++ b/apps/files_sharing/l10n/es.js @@ -1,7 +1,7 @@ OC.L10N.register( "files_sharing", { - "Shared with you" : "Compartido con usted", + "Shared with you" : "Compartido contigo", "Shared with others" : "Compartido con otros", "Shared by link" : "Compartido por medio de enlaces", "Nothing shared with you yet" : "TodavÃa no han compartido nada contigo", @@ -36,10 +36,13 @@ OC.L10N.register( "Public link expired" : "El enlace público ha expirado", "{actor} shared as public link" : "{actor} compartió como enlace público", "{actor} removed public link" : "{actor} eliminó el enlace público", + "Public link of {actor} expired" : "Enlace público de {actor} caducado", "You shared {file} as public link" : "Compartió {file} como un enlace público", "You removed public link for {file}" : "Eliminó el enlace público para {file}", + "Public link expired for {file}" : "Enlace público caducado para {file}", "{actor} shared {file} as public link" : "{actor} compartió {file} como enlace público", "{actor} removed public link for {file}" : "{actor} eliminó el enlace público para {file}", + "Public link of {actor} for {file} expired" : "Enlace público de {actor} para {file} caducado", "{user} accepted the remote share" : "{user} aceptó el recurso compartido remotamente", "{user} declined the remote share" : "{user} rechazó el recurso compartido", "You received a new remote share {file} from {user}" : "Ha recibido un nuevo recurso compartido remoto {file} de {user}", diff --git a/apps/files_sharing/l10n/es.json b/apps/files_sharing/l10n/es.json index e776d9ba8ce..5df6c6331ec 100644 --- a/apps/files_sharing/l10n/es.json +++ b/apps/files_sharing/l10n/es.json @@ -1,5 +1,5 @@ { "translations": { - "Shared with you" : "Compartido con usted", + "Shared with you" : "Compartido contigo", "Shared with others" : "Compartido con otros", "Shared by link" : "Compartido por medio de enlaces", "Nothing shared with you yet" : "TodavÃa no han compartido nada contigo", @@ -34,10 +34,13 @@ "Public link expired" : "El enlace público ha expirado", "{actor} shared as public link" : "{actor} compartió como enlace público", "{actor} removed public link" : "{actor} eliminó el enlace público", + "Public link of {actor} expired" : "Enlace público de {actor} caducado", "You shared {file} as public link" : "Compartió {file} como un enlace público", "You removed public link for {file}" : "Eliminó el enlace público para {file}", + "Public link expired for {file}" : "Enlace público caducado para {file}", "{actor} shared {file} as public link" : "{actor} compartió {file} como enlace público", "{actor} removed public link for {file}" : "{actor} eliminó el enlace público para {file}", + "Public link of {actor} for {file} expired" : "Enlace público de {actor} para {file} caducado", "{user} accepted the remote share" : "{user} aceptó el recurso compartido remotamente", "{user} declined the remote share" : "{user} rechazó el recurso compartido", "You received a new remote share {file} from {user}" : "Ha recibido un nuevo recurso compartido remoto {file} de {user}", diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js index 8b30859a00d..515f15fd091 100644 --- a/apps/files_sharing/l10n/pl.js +++ b/apps/files_sharing/l10n/pl.js @@ -28,7 +28,7 @@ OC.L10N.register( "{actor} shared with group {group}" : "{actor} udostÄ™pniÅ‚ grupie {group}", "{actor} removed share for group {group}" : "{actor} zakoÅ„czyÅ‚ udostÄ™pnianie grupie {group}", "You shared {file} with group {group}" : "UdostÄ™pniasz {file} grupie {group}", - "You removed group {group} from {file}" : "UsunÄ…Å‚eÅ› grupÄ™ {group} z {file}", + "You removed group {group} from {file}" : "UsuniÄ™to grupÄ™ {group} z {file}", "{actor} shared {file} with group {group}" : "{actor} udostÄ™pniÅ‚ {file} grupie {group}", "{actor} removed group {group} from {file}" : "{actor} usunÄ…Å‚ grupÄ™ {group} z {file}", "Shared as public link" : "UdostÄ™pnione jako publiczny link", @@ -127,9 +127,11 @@ OC.L10N.register( "Shared with %3$s by %2$s" : "UdostÄ™pniono użytkownikowi %3$s przez %2$s", "Shared with group %2$s" : "UdostÄ™pniono grupie %2$s", "Shared with group %3$s by %2$s" : "UdostÄ™pniono grupie %3$s przez użytkownika %2$s", + "%2$s removed share of group %3$s" : "%2$s usunÄ…Å‚(-ęła) udostÄ™pnianie grupie %3$s", "Shared via link by %2$s" : "UdostÄ™pniono za pomocÄ… Å‚Ä…cza przez użytkownika %2$s", "Shared via public link" : "UdostÄ™pniono przez publiczne Å‚Ä…cze", "%2$s removed public link" : "%2$s usunÄ…Å‚ publiczne Å‚Ä…cze", + "Public link of %2$s expired" : "Publiczne Å‚Ä…cze użytkownika %2$s wygasÅ‚o", "Shared by %2$s" : "UdostÄ™pniane przez %2$s", "Shares" : "UdziaÅ‚y", "Downloaded by %1$s" : "Pobierane przez %1$s", diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json index 5cbdbcb85e6..14db7d9b38f 100644 --- a/apps/files_sharing/l10n/pl.json +++ b/apps/files_sharing/l10n/pl.json @@ -26,7 +26,7 @@ "{actor} shared with group {group}" : "{actor} udostÄ™pniÅ‚ grupie {group}", "{actor} removed share for group {group}" : "{actor} zakoÅ„czyÅ‚ udostÄ™pnianie grupie {group}", "You shared {file} with group {group}" : "UdostÄ™pniasz {file} grupie {group}", - "You removed group {group} from {file}" : "UsunÄ…Å‚eÅ› grupÄ™ {group} z {file}", + "You removed group {group} from {file}" : "UsuniÄ™to grupÄ™ {group} z {file}", "{actor} shared {file} with group {group}" : "{actor} udostÄ™pniÅ‚ {file} grupie {group}", "{actor} removed group {group} from {file}" : "{actor} usunÄ…Å‚ grupÄ™ {group} z {file}", "Shared as public link" : "UdostÄ™pnione jako publiczny link", @@ -125,9 +125,11 @@ "Shared with %3$s by %2$s" : "UdostÄ™pniono użytkownikowi %3$s przez %2$s", "Shared with group %2$s" : "UdostÄ™pniono grupie %2$s", "Shared with group %3$s by %2$s" : "UdostÄ™pniono grupie %3$s przez użytkownika %2$s", + "%2$s removed share of group %3$s" : "%2$s usunÄ…Å‚(-ęła) udostÄ™pnianie grupie %3$s", "Shared via link by %2$s" : "UdostÄ™pniono za pomocÄ… Å‚Ä…cza przez użytkownika %2$s", "Shared via public link" : "UdostÄ™pniono przez publiczne Å‚Ä…cze", "%2$s removed public link" : "%2$s usunÄ…Å‚ publiczne Å‚Ä…cze", + "Public link of %2$s expired" : "Publiczne Å‚Ä…cze użytkownika %2$s wygasÅ‚o", "Shared by %2$s" : "UdostÄ™pniane przez %2$s", "Shares" : "UdziaÅ‚y", "Downloaded by %1$s" : "Pobierane przez %1$s", diff --git a/apps/files_sharing/l10n/pt_BR.js b/apps/files_sharing/l10n/pt_BR.js index e224d405bb5..5bf4da4924d 100644 --- a/apps/files_sharing/l10n/pt_BR.js +++ b/apps/files_sharing/l10n/pt_BR.js @@ -36,10 +36,13 @@ OC.L10N.register( "Public link expired" : "O link público expirou", "{actor} shared as public link" : "{actor} compartilhado como um link publico", "{actor} removed public link" : "{actor} removido link publico", + "Public link of {actor} expired" : "O Link público de {actor} expirou.", "You shared {file} as public link" : "Voce compartilhou {file} como um link publico", "You removed public link for {file}" : "Voce removeu o link publico para {file}", + "Public link expired for {file}" : "O Link Público para {file} expirou", "{actor} shared {file} as public link" : "{actor} compartilhado {file} como um link publico", "{actor} removed public link for {file}" : "{actor} removido link publico para {file}", + "Public link of {actor} for {file} expired" : "O Link Público de {actor} para {file} espirou", "{user} accepted the remote share" : "{user} aceitou o compartilhamento remoto", "{user} declined the remote share" : "{user} declinou do compartilhamento remoto", "You received a new remote share {file} from {user}" : "Voce recebeu um novo compartilhamento remoto {file} de {user}", diff --git a/apps/files_sharing/l10n/pt_BR.json b/apps/files_sharing/l10n/pt_BR.json index ebce9119185..8019c841685 100644 --- a/apps/files_sharing/l10n/pt_BR.json +++ b/apps/files_sharing/l10n/pt_BR.json @@ -34,10 +34,13 @@ "Public link expired" : "O link público expirou", "{actor} shared as public link" : "{actor} compartilhado como um link publico", "{actor} removed public link" : "{actor} removido link publico", + "Public link of {actor} expired" : "O Link público de {actor} expirou.", "You shared {file} as public link" : "Voce compartilhou {file} como um link publico", "You removed public link for {file}" : "Voce removeu o link publico para {file}", + "Public link expired for {file}" : "O Link Público para {file} expirou", "{actor} shared {file} as public link" : "{actor} compartilhado {file} como um link publico", "{actor} removed public link for {file}" : "{actor} removido link publico para {file}", + "Public link of {actor} for {file} expired" : "O Link Público de {actor} para {file} espirou", "{user} accepted the remote share" : "{user} aceitou o compartilhamento remoto", "{user} declined the remote share" : "{user} declinou do compartilhamento remoto", "You received a new remote share {file} from {user}" : "Voce recebeu um novo compartilhamento remoto {file} de {user}", diff --git a/apps/files_sharing/lib/Activity/Providers/RemoteShares.php b/apps/files_sharing/lib/Activity/Providers/RemoteShares.php index 425defe57e4..4e7d8ef3e27 100644 --- a/apps/files_sharing/lib/Activity/Providers/RemoteShares.php +++ b/apps/files_sharing/lib/Activity/Providers/RemoteShares.php @@ -24,18 +24,39 @@ 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 * @throws \InvalidArgumentException @@ -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(), ]; } } diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index 403d30ae2e6..c8cf723630b 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -35,6 +35,7 @@ use OC\AppFramework\Utility\SimpleContainer; use OCA\Files_Sharing\Controller\ExternalSharesController; use OCA\Files_Sharing\Controller\ShareController; use OCA\Files_Sharing\Middleware\SharingCheckMiddleware; +use OCP\Federation\ICloudIdManager; use \OCP\IContainer; use OCP\IServerContainer; @@ -84,6 +85,9 @@ class Application extends App { $container->registerService('HttpClientService', function (SimpleContainer $c) use ($server) { return $server->getHTTPClientService(); }); + $container->registerService(ICloudIdManager::class, function (SimpleContainer $c) use ($server) { + return $server->getCloudIdManager(); + }); $container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) { $user = $server->getUserSession()->getUser(); $uid = $user ? $user->getUID() : null; @@ -145,7 +149,8 @@ class Application extends App { $server->getDatabaseConnection(), function() use ($c) { return $c->query('ExternalManager'); - } + }, + $server->getCloudIdManager() ); }); diff --git a/apps/files_sharing/lib/Controller/ShareesAPIController.php b/apps/files_sharing/lib/Controller/ShareesAPIController.php index cd5139693cf..40a9b272bc8 100644 --- a/apps/files_sharing/lib/Controller/ShareesAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareesAPIController.php @@ -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'); } /** diff --git a/apps/files_sharing/lib/External/Cache.php b/apps/files_sharing/lib/External/Cache.php index eaf8e0c4acf..c7793cf0595 100644 --- a/apps/files_sharing/lib/External/Cache.php +++ b/apps/files_sharing/lib/External/Cache.php @@ -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; } diff --git a/apps/files_sharing/lib/External/MountProvider.php b/apps/files_sharing/lib/External/MountProvider.php index 3f2f39a74f7..27ee9fcb46b 100644 --- a/apps/files_sharing/lib/External/MountProvider.php +++ b/apps/files_sharing/lib/External/MountProvider.php @@ -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; @@ -41,12 +42,19 @@ 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); diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php index 93f3571e803..51d97388db7 100644 --- a/apps/files_sharing/lib/External/Storage.php +++ b/apps/files_sharing/lib/External/Storage.php @@ -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) { diff --git a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php index c68e2304743..035085d811a 100644 --- a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php @@ -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(); diff --git a/apps/files_sharing/tests/External/CacheTest.php b/apps/files_sharing/tests/External/CacheTest.php index a31a748a69b..0129e760648 100644 --- a/apps/files_sharing/tests/External/CacheTest.php +++ b/apps/files_sharing/tests/External/CacheTest.php @@ -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', diff --git a/apps/files_sharing/tests/External/ManagerTest.php b/apps/files_sharing/tests/External/ManagerTest.php index 48476888bdd..f2a55babcc7 100644 --- a/apps/files_sharing/tests/External/ManagerTest.php +++ b/apps/files_sharing/tests/External/ManagerTest.php @@ -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() { diff --git a/apps/files_sharing/tests/ExternalStorageTest.php b/apps/files_sharing/tests/ExternalStorageTest.php index 49b72be1391..1246b0edb98 100644 --- a/apps/files_sharing/tests/ExternalStorageTest.php +++ b/apps/files_sharing/tests/ExternalStorageTest.php @@ -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', diff --git a/apps/sharebymail/l10n/.gitkeep b/apps/sharebymail/l10n/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/apps/sharebymail/l10n/.gitkeep diff --git a/apps/systemtags/l10n/sq.js b/apps/systemtags/l10n/sq.js index 3c1c1b4f039..424c221d3e8 100644 --- a/apps/systemtags/l10n/sq.js +++ b/apps/systemtags/l10n/sq.js @@ -34,6 +34,7 @@ OC.L10N.register( "%s (invisible)" : "%s (e padukshme)", "<strong>System tags</strong> for a file have been modified" : "U ndryshyan <strong>etiketa sistemi</strong>për një kartelë", "Name" : "Emër", + "Invisible" : "I padukshëm", "No files in here" : "S’ka kartela këtu", "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", "Size" : "Madhësi", diff --git a/apps/systemtags/l10n/sq.json b/apps/systemtags/l10n/sq.json index 31b30a1ffa3..9e9f5789040 100644 --- a/apps/systemtags/l10n/sq.json +++ b/apps/systemtags/l10n/sq.json @@ -32,6 +32,7 @@ "%s (invisible)" : "%s (e padukshme)", "<strong>System tags</strong> for a file have been modified" : "U ndryshyan <strong>etiketa sistemi</strong>për një kartelë", "Name" : "Emër", + "Invisible" : "I padukshëm", "No files in here" : "S’ka kartela këtu", "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", "Size" : "Madhësi", diff --git a/apps/workflowengine/l10n/pl.js b/apps/workflowengine/l10n/pl.js index 9b1d324469c..ebec68bd463 100644 --- a/apps/workflowengine/l10n/pl.js +++ b/apps/workflowengine/l10n/pl.js @@ -60,7 +60,7 @@ OC.L10N.register( "Check #%s does not exist" : "Sprawdź, czy #%s nie istnieje", "Workflow" : "WpÅ‚yw na pracÄ™", "Open documentation" : "Otwórz dokumentacjÄ™", - "Add rule group" : "Dodaj reguÅ‚Ä™ grupy", + "Add rule group" : "Dodaj grupÄ™ reguÅ‚", "Short rule description" : "Krótki opis reguÅ‚y", "Add rule" : "Dodaj reguÅ‚Ä™", "Reset" : "Zresetuj", diff --git a/apps/workflowengine/l10n/pl.json b/apps/workflowengine/l10n/pl.json index f60c8750f26..9c0c69f914e 100644 --- a/apps/workflowengine/l10n/pl.json +++ b/apps/workflowengine/l10n/pl.json @@ -58,7 +58,7 @@ "Check #%s does not exist" : "Sprawdź, czy #%s nie istnieje", "Workflow" : "WpÅ‚yw na pracÄ™", "Open documentation" : "Otwórz dokumentacjÄ™", - "Add rule group" : "Dodaj reguÅ‚Ä™ grupy", + "Add rule group" : "Dodaj grupÄ™ reguÅ‚", "Short rule description" : "Krótki opis reguÅ‚y", "Add rule" : "Dodaj reguÅ‚Ä™", "Reset" : "Zresetuj", diff --git a/build/integration/features/bootstrap/CalDavContext.php b/build/integration/features/bootstrap/CalDavContext.php index 5db56f0fe7a..cae0089875f 100644 --- a/build/integration/features/bootstrap/CalDavContext.php +++ b/build/integration/features/bootstrap/CalDavContext.php @@ -72,16 +72,18 @@ class CalDavContext implements \Behat\Behat\Context\Context { } /** - * @When :user requests calendar :calendar + * @When :user requests calendar :calendar on the endpoint :endpoint * @param string $user * @param string $calendar + * @param string $endpoint */ - public function requestsCalendar($user, $calendar) { - $davUrl = $this->baseUrl . '/remote.php/dav/calendars/'.$calendar; + public function requestsCalendar($user, $calendar, $endpoint) { + $davUrl = $this->baseUrl . $endpoint . $calendar; $password = ($user === 'admin') ? 'admin' : '123456'; try { - $this->response = $this->client->get( + $request = $this->client->createRequest( + 'PROPFIND', $davUrl, [ 'auth' => [ @@ -90,6 +92,7 @@ class CalDavContext implements \Behat\Behat\Context\Context { ] ] ); + $this->response = $this->client->send($request); } catch (\GuzzleHttp\Exception\ClientException $e) { $this->response = $e->getResponse(); } diff --git a/build/integration/features/bootstrap/CardDavContext.php b/build/integration/features/bootstrap/CardDavContext.php index 4ee882cc2e6..2dce688ab85 100644 --- a/build/integration/features/bootstrap/CardDavContext.php +++ b/build/integration/features/bootstrap/CardDavContext.php @@ -72,20 +72,21 @@ class CardDavContext implements \Behat\Behat\Context\Context { } catch (\GuzzleHttp\Exception\ClientException $e) {} } - /** - * @When :user requests addressbook :addressBook with statuscode :statusCode + * @When :user requests addressbook :addressBook with statuscode :statusCode on the endpoint :endpoint * @param string $user * @param string $addressBook * @param int $statusCode + * @param string $endpoint * @throws \Exception */ - public function requestsAddressbookWithStatuscode($user, $addressBook, $statusCode) { - $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/'.$addressBook; + public function requestsAddressbookWithStatuscodeOnTheEndpoint($user, $addressBook, $statusCode, $endpoint) { + $davUrl = $this->baseUrl . $endpoint . $addressBook; $password = ($user === 'admin') ? 'admin' : '123456'; try { - $this->response = $this->client->get( + $request = $this->client->createRequest( + 'PROPFIND', $davUrl, [ 'auth' => [ @@ -94,6 +95,7 @@ class CardDavContext implements \Behat\Behat\Context\Context { ], ] ); + $this->response = $this->client->send($request); } catch (\GuzzleHttp\Exception\ClientException $e) { $this->response = $e->getResponse(); } diff --git a/build/integration/features/caldav.feature b/build/integration/features/caldav.feature index 948151485db..5c3983fc40b 100644 --- a/build/integration/features/caldav.feature +++ b/build/integration/features/caldav.feature @@ -1,31 +1,52 @@ Feature: caldav Scenario: Accessing a not existing calendar of another user Given user "user0" exists - When "admin" requests calendar "user0/MyCalendar" + When "admin" requests calendar "user0/MyCalendar" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" And The exception is "Sabre\DAV\Exception\NotFound" And The error message is "Node with name 'MyCalendar' could not be found" - # Blocked by https://github.com/php/php-src/pull/1417 - #Scenario: Accessing a not shared calendar of another user - # Given user "user0" exists - # Given "admin" creates a calendar named "MyCalendar" - # Given The CalDAV HTTP status code should be "201" - # When "user0" requests calendar "admin/MyCalendar" - # Then The CalDAV HTTP status code should be "404" - # And The exception is "Sabre\DAV\Exception\NotFound" - # And The error message is "Node with name 'MyCalendar' could not be found" + Scenario: Accessing a not shared calendar of another user + Given user "user0" exists + Given "admin" creates a calendar named "MyCalendar" + Given The CalDAV HTTP status code should be "201" + When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" + Then The CalDAV HTTP status code should be "404" + And The exception is "Sabre\DAV\Exception\NotFound" + And The error message is "Node with name 'MyCalendar' could not be found" + + Scenario: Accessing a not shared calendar of another user via the legacy endpoint + Given user "user0" exists + Given "admin" creates a calendar named "MyCalendar" + Given The CalDAV HTTP status code should be "201" + When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/caldav/calendars/" + Then The CalDAV HTTP status code should be "404" + And The exception is "Sabre\DAV\Exception\NotFound" + And The error message is "Node with name 'MyCalendar' could not be found" + + Scenario: Accessing a not existing calendar of another user + Given user "user0" exists + When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" + Then The CalDAV HTTP status code should be "404" + And The exception is "Sabre\DAV\Exception\NotFound" + And The error message is "Node with name 'MyCalendar' could not be found" + + Scenario: Accessing a not existing calendar of another user via the legacy endpoint + Given user "user0" exists + When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/caldav/calendars/" + Then The CalDAV HTTP status code should be "404" + And The exception is "Sabre\DAV\Exception\NotFound" + And The error message is "Node with name 'MyCalendar' could not be found" Scenario: Accessing a not existing calendar of myself Given user "user0" exists - When "user0" requests calendar "admin/MyCalendar" + When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" And The exception is "Sabre\DAV\Exception\NotFound" And The error message is "Node with name 'MyCalendar' could not be found" - # Blocked by https://github.com/php/php-src/pull/1417 - #Scenario: Creating a new calendar - # When "admin" creates a calendar named "MyCalendar" - # Then The CalDAV HTTP status code should be "201" - # And "admin" requests calendar "admin/MyCalendar" - # Then The CalDAV HTTP status code should be "200" + Scenario: Creating a new calendar + When "admin" creates a calendar named "MyCalendar" + Then The CalDAV HTTP status code should be "201" + And "admin" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" + Then The CalDAV HTTP status code should be "207" diff --git a/build/integration/features/carddav.feature b/build/integration/features/carddav.feature index 4fbe403c7db..9432130066e 100644 --- a/build/integration/features/carddav.feature +++ b/build/integration/features/carddav.feature @@ -1,26 +1,39 @@ Feature: carddav Scenario: Accessing a not existing addressbook of another user Given user "user0" exists - When "admin" requests addressbook "user0/MyAddressbook" with statuscode "404" + When "admin" requests addressbook "user0/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/dav/addressbooks/users/" And The CardDAV exception is "Sabre\DAV\Exception\NotFound" And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" Scenario: Accessing a not shared addressbook of another user Given user "user0" exists Given "admin" creates an addressbook named "MyAddressbook" with statuscode "201" - When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" + When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/dav/addressbooks/users/" + And The CardDAV exception is "Sabre\DAV\Exception\NotFound" + And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" + + Scenario: Accessing a not existing addressbook of another user via legacy endpoint + Given user "user0" exists + When "admin" requests addressbook "user0/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/carddav/addressbooks/" + And The CardDAV exception is "Sabre\DAV\Exception\NotFound" + And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" + + Scenario: Accessing a not shared addressbook of another user via legacy endpoint + Given user "user0" exists + Given "admin" creates an addressbook named "MyAddressbook" with statuscode "201" + When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/carddav/addressbooks/" And The CardDAV exception is "Sabre\DAV\Exception\NotFound" And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" Scenario: Accessing a not existing addressbook of myself Given user "user0" exists - When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" + When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/dav/addressbooks/users/" And The CardDAV exception is "Sabre\DAV\Exception\NotFound" And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" Scenario: Creating a new addressbook When "admin" creates an addressbook named "MyAddressbook" with statuscode "201" - Then "admin" requests addressbook "admin/MyAddressbook" with statuscode "200" + Then "admin" requests addressbook "admin/MyAddressbook" with statuscode "207" on the endpoint "/remote.php/dav/addressbooks/users/" Scenario: Accessing ones own contact Given "admin" creates an addressbook named "MyAddressbook" with statuscode "201" diff --git a/core/Command/User/Setting.php b/core/Command/User/Setting.php index 368a0c15dcd..d7bb436783f 100644 --- a/core/Command/User/Setting.php +++ b/core/Command/User/Setting.php @@ -25,6 +25,7 @@ namespace OC\Core\Command\User; use OC\Core\Command\Base; use OCP\IConfig; use OCP\IDBConnection; +use OCP\IUser; use OCP\IUserManager; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -174,6 +175,14 @@ class Setting extends Base { return 1; } + if ($app === 'settings' && $key === 'email') { + $user = $this->userManager->get($uid); + if ($user instanceof IUser) { + $user->setEMailAddress($input->getArgument('value')); + return 0; + } + } + $this->config->setUserValue($uid, $app, $key, $input->getArgument('value')); return 0; @@ -183,6 +192,14 @@ class Setting extends Base { return 1; } + if ($app === 'settings' && $key === 'email') { + $user = $this->userManager->get($uid); + if ($user instanceof IUser) { + $user->setEMailAddress(''); + return 0; + } + } + $this->config->deleteUserValue($uid, $app, $key); return 0; diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php index 28cc39b9137..954a18e8778 100644 --- a/core/Controller/LoginController.php +++ b/core/Controller/LoginController.php @@ -98,7 +98,7 @@ class LoginController extends Controller { * @return RedirectResponse */ public function logout() { - $loginToken = $this->request->getCookie('oc_token'); + $loginToken = $this->request->getCookie('nc_token'); if (!is_null($loginToken)) { $this->config->deleteUserValue($this->userSession->getUser()->getUID(), 'login_token', $loginToken); } diff --git a/core/js/js.js b/core/js/js.js index 3651635541a..5ef5c72f625 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -780,8 +780,18 @@ var OCP = {}, // sometimes "beforeunload" happens later, so need to defer the reload a bit setTimeout(function() { if (!self._userIsNavigatingAway && !self._reloadCalled) { - OC.Notification.show(t('core', 'Problem loading page, reloading in 5 seconds')); - setTimeout(OC.reload, 5000); + var timer = 0; + var seconds = 5; + var interval = setInterval( function() { + OC.Notification.showUpdate(n('core', 'Problem loading page, reloading in %n second', 'Problem loading page, reloading in %n seconds', seconds - timer)); + if (timer >= seconds) { + clearInterval(interval); + OC.reload(); + } + timer++; + }, 1000 // 1 second interval + ); + // only call reload once self._reloadCalled = true; } @@ -1174,6 +1184,30 @@ OC.Notification={ }, /** + * Updates (replaces) a sanitized notification. + * + * @param {string} text Message to display + * @return {jQuery} JQuery element for notificaiton row + */ + showUpdate: function(text) { + var $notification = $('#notification'); + // sanitise + var $html = $('<div/>').text(text).html(); + + // new notification + if (text && $notification.find('.row').length == 0) { + return this.showHtml($html); + } + + var $row = $('<div class="row"></div>').prepend($html); + + // just update html in notification + $notification.html($row); + + return $row; + }, + + /** * Shows a notification that disappears after x seconds, default is * 7 seconds * diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index d83c0cd9a38..3380b6be420 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -1000,7 +1000,7 @@ describe('Core base tests', function() { describe('global ajax errors', function() { var reloadStub, ajaxErrorStub, clock; var notificationStub; - var waitTimeMs = 6000; + var waitTimeMs = 6500; var oldCurrentUser; beforeEach(function() { @@ -1075,10 +1075,12 @@ describe('Core base tests', function() { it('displays notification', function() { var xhr = { status: 401 }; + notificationUpdateStub = sinon.stub(OC.Notification, 'showUpdate'); + $(document).trigger(new $.Event('ajaxError'), xhr); clock.tick(waitTimeMs); - expect(notificationStub.calledOnce).toEqual(true); + expect(notificationUpdateStub.notCalled).toEqual(false); }); it('shows a temporary notification if the connection is lost', function() { var xhr = { status: 0 }; diff --git a/issue_template.md b/issue_template.md index 70eca36c9b6..6714371a4eb 100644 --- a/issue_template.md +++ b/issue_template.md @@ -104,6 +104,7 @@ Eventually replace sensitive data as the name/IP-address of your LDAP server or #### Web server error log <details> <summary>Web server error log</summary> + ``` Insert your webserver log here ``` @@ -112,6 +113,7 @@ Insert your webserver log here #### Nextcloud log (data/nextcloud.log) <details> <summary>Nextcloud log</summary> + ``` Insert your Nextcloud log here ``` @@ -120,6 +122,7 @@ Insert your Nextcloud log here #### Browser log <details> <summary>Browser log</summary> + ``` Insert your browser log here, this could for example include: diff --git a/l10n/.tx/config b/l10n/.tx/config index 3554cf6954b..3368c3e7097 100644 --- a/l10n/.tx/config +++ b/l10n/.tx/config @@ -86,6 +86,12 @@ source_file = templates/federation.pot source_lang = en type = PO +[nextcloud.sharebymail] +file_filter = <lang>/sharebymail.po +source_file = templates/sharebymail.pot +source_lang = en +type = PO + [nextcloud.systemtags] file_filter = <lang>/systemtags.po source_file = templates/systemtags.pot 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/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 62d7fc7ed30..be35f4d172f 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -72,7 +72,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { /** * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_IOS instead */ - const USER_AGENT_OWNCLOUD_IOS = '/^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/'; + const USER_AGENT_OWNCLOUD_IOS = '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/'; /** * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_ANDROID instead */ @@ -490,7 +490,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @return bool */ private function cookieCheckRequired() { - if($this->getCookie(session_name()) === null && $this->getCookie('oc_token') === null) { + if($this->getCookie(session_name()) === null && $this->getCookie('nc_token') === null) { return false; } 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/Lockdown/Filesystem/NullStorage.php b/lib/private/Lockdown/Filesystem/NullStorage.php index 967b6d2c6e7..ea911b90064 100644 --- a/lib/private/Lockdown/Filesystem/NullStorage.php +++ b/lib/private/Lockdown/Filesystem/NullStorage.php @@ -20,6 +20,7 @@ namespace OC\Lockdown\Filesystem; use Icewind\Streams\IteratorDirectory; +use OC\Files\FileInfo; use OC\Files\Storage\Common; class NullStorage extends Common { @@ -128,7 +129,7 @@ class NullStorage extends Common { } public function free_space($path) { - return 0; + return FileInfo::SPACE_UNKNOWN; } public function touch($path, $mtime = null) { diff --git a/lib/private/Log.php b/lib/private/Log.php index fddd3593127..bcaa788603a 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -88,7 +88,8 @@ class Log implements ILogger { 'decrypt', //LoginController - 'tryLogin' + 'tryLogin', + 'confirmPassword', ]; /** 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/Setup.php b/lib/private/Setup.php index d9997767684..321e8ea4c66 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -357,6 +357,7 @@ class Setup { $config = \OC::$server->getConfig(); $config->setAppValue('core', 'installedat', microtime(true)); $config->setAppValue('core', 'lastupdatedat', microtime(true)); + $config->setAppValue('core', 'vendor', $this->getVendor()); $group =\OC::$server->getGroupManager()->createGroup('admin'); $group->addUser($user); @@ -497,4 +498,18 @@ class Setup { file_put_contents($baseDir . '/.htaccess', $content); file_put_contents($baseDir . '/index.html', ''); } + + /** + * Return vendor from which this version was published + * + * @return string Get the vendor + * + * Copy of \OC\Updater::getVendor() + */ + private function getVendor() { + // this should really be a JSON file + require \OC::$SERVERROOT . '/version.php'; + /** @var string $vendor */ + return (string) $vendor; + } } 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/Updater.php b/lib/private/Updater.php index a66d49941cd..30a9a80cef4 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -157,13 +157,13 @@ class Updater extends BasicEmitter { /** * Return version from which this version is allowed to upgrade from * - * @return string allowed previous version + * @return array allowed previous versions per vendor */ - private function getAllowedPreviousVersion() { + private function getAllowedPreviousVersions() { // this should really be a JSON file require \OC::$SERVERROOT . '/version.php'; /** @var array $OC_VersionCanBeUpgradedFrom */ - return implode('.', $OC_VersionCanBeUpgradedFrom); + return $OC_VersionCanBeUpgradedFrom; } /** @@ -182,26 +182,22 @@ class Updater extends BasicEmitter { * Whether an upgrade to a specified version is possible * @param string $oldVersion * @param string $newVersion - * @param string $allowedPreviousVersion + * @param array $allowedPreviousVersions * @return bool */ - public function isUpgradePossible($oldVersion, $newVersion, $allowedPreviousVersion) { - $allowedUpgrade = (version_compare($allowedPreviousVersion, $oldVersion, '<=') - && (version_compare($oldVersion, $newVersion, '<=') || $this->config->getSystemValue('debug', false))); - - if ($allowedUpgrade) { - return $allowedUpgrade; + public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) { + $version = explode('.', $oldVersion); + $majorMinor = $version[0] . '.' . $version[1]; + + $currentVendor = $this->config->getAppValue('core', 'vendor', ''); + if ($currentVendor === 'nextcloud') { + return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) + && (version_compare($oldVersion, $newVersion, '<=') || + $this->config->getSystemValue('debug', false)); } - // Upgrade not allowed, someone switching vendor? - if ($this->getVendor() !== $this->config->getAppValue('core', 'vendor', '')) { - $oldVersion = explode('.', $oldVersion); - $newVersion = explode('.', $newVersion); - - return $oldVersion[0] === $newVersion[0] && $oldVersion[1] === $newVersion[1]; - } - - return false; + // Check if the instance can be migrated + return isset($allowedPreviousVersions[$currentVendor][$majorMinor]); } /** @@ -215,8 +211,8 @@ class Updater extends BasicEmitter { */ private function doUpgrade($currentVersion, $installedVersion) { // Stop update if the update is over several major versions - $allowedPreviousVersion = $this->getAllowedPreviousVersion(); - if (!self::isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersion)) { + $allowedPreviousVersions = $this->getAllowedPreviousVersions(); + if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) { throw new \Exception('Updates between multiple major versions and downgrades are unsupported.'); } 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..f9c84a2fd07 --- /dev/null +++ b/lib/public/Federation/ICloudId.php @@ -0,0 +1,60 @@ +<?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 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(); +} diff --git a/lib/public/Federation/ICloudIdManager.php b/lib/public/Federation/ICloudIdManager.php new file mode 100644 index 00000000000..7be8f08c6b7 --- /dev/null +++ b/lib/public/Federation/ICloudIdManager.php @@ -0,0 +1,57 @@ +<?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 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); +} diff --git a/lib/public/IRequest.php b/lib/public/IRequest.php index b36a934b0c2..98d8f5bb83a 100644 --- a/lib/public/IRequest.php +++ b/lib/public/IRequest.php @@ -76,7 +76,7 @@ interface IRequest { /** * @since 9.1.0 */ - const USER_AGENT_CLIENT_IOS = '/^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/'; + const USER_AGENT_CLIENT_IOS = '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/'; /** * @param string $name 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(); } diff --git a/ocs/v1.php b/ocs/v1.php index 79e74f20cdf..31eb0687955 100644 --- a/ocs/v1.php +++ b/ocs/v1.php @@ -90,6 +90,7 @@ try { } catch (\OC\User\LoginException $e) { OC_API::respond(new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED, 'Unauthorised')); } catch (\Exception $e) { + \OC::$server->getLogger()->logException($e); OC_API::setContentType(); OC_OCS::notFound(); } diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index a81e05cb3ed..365057b5fc6 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -131,7 +131,7 @@ androidChrome: /Android.*(?:; (.*) Build\/).*Chrome\/(\d+)[0-9.]+/, iphone: / *CPU +iPhone +OS +([0-9]+)_(?:[0-9_])+ +like +Mac +OS +X */, ipad: /\(iPad\; *CPU +OS +([0-9]+)_(?:[0-9_])+ +like +Mac +OS +X */, - iosClient: /^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/, + iosClient: /^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/, androidClient:/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/, // DAVdroid/1.2 (2016/07/03; dav4android; okhttp3) Android/6.0.1 davDroid: /DAVdroid\/([0-9.]+)/, diff --git a/tests/Core/Controller/LoginControllerTest.php b/tests/Core/Controller/LoginControllerTest.php index a1a4452abf8..72f921724a5 100644 --- a/tests/Core/Controller/LoginControllerTest.php +++ b/tests/Core/Controller/LoginControllerTest.php @@ -89,7 +89,7 @@ class LoginControllerTest extends TestCase { $this->request ->expects($this->once()) ->method('getCookie') - ->with('oc_token') + ->with('nc_token') ->willReturn(null); $this->config ->expects($this->never()) @@ -108,7 +108,7 @@ class LoginControllerTest extends TestCase { $this->request ->expects($this->once()) ->method('getCookie') - ->with('oc_token') + ->with('nc_token') ->willReturn('MyLoginToken'); $user = $this->getMockBuilder('\\OCP\\IUser')->getMock(); $user diff --git a/tests/lib/AppFramework/Http/RequestTest.php b/tests/lib/AppFramework/Http/RequestTest.php index b1515b0efb5..6c6504b4de8 100644 --- a/tests/lib/AppFramework/Http/RequestTest.php +++ b/tests/lib/AppFramework/Http/RequestTest.php @@ -1651,7 +1651,7 @@ class RequestTest extends \Test\TestCase { 'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds', ], 'cookies' => [ - 'oc_token' => 'asdf', + 'nc_token' => 'asdf', ], ], $this->secureRandom, diff --git a/tests/lib/Federation/CloudIdManagerTest.php b/tests/lib/Federation/CloudIdManagerTest.php new file mode 100644 index 00000000000..fe673588bba --- /dev/null +++ b/tests/lib/Federation/CloudIdManagerTest.php @@ -0,0 +1,99 @@ +<?php +/** + * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> + * + * @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\Federation; + +use OC\Federation\CloudIdManager; +use Test\TestCase; + +class CloudIdManagerTest extends TestCase { + /** @var CloudIdManager */ + private $cloudIdManager; + + protected function setUp() { + parent::setUp(); + $this->cloudIdManager = new CloudIdManager(); + } + + public function cloudIdProvider() { + return [ + ['test@example.com', 'test', 'example.com', 'test@example.com'], + ['test@example.com/cloud', 'test', 'example.com/cloud', 'test@example.com/cloud'], + ['test@example.com/cloud/', 'test', 'example.com/cloud', 'test@example.com/cloud'], + ['test@example.com/cloud/index.php', 'test', 'example.com/cloud', 'test@example.com/cloud'], + ['test@example.com@example.com', 'test@example.com', 'example.com', 'test@example.com@example.com'], + ]; + } + + /** + * @dataProvider cloudIdProvider + * + * @param string $cloudId + * @param string $user + * @param string $remote + */ + public function testResolveCloudId($cloudId, $user, $remote, $cleanId) { + $cloudId = $this->cloudIdManager->resolveCloudId($cloudId); + + $this->assertEquals($user, $cloudId->getUser()); + $this->assertEquals($remote, $cloudId->getRemote()); + $this->assertEquals($cleanId, $cloudId->getId()); + } + + public function invalidCloudIdProvider() { + return [ + ['example.com'], + ['test:foo@example.com'], + ['test/foo@example.com'] + ]; + } + + /** + * @dataProvider invalidCloudIdProvider + * + * @param string $cloudId + * + * @expectedException \InvalidArgumentException + */ + public function testInvalidCloudId($cloudId) { + $this->cloudIdManager->resolveCloudId($cloudId); + } + + public function getCloudIdProvider() { + return [ + ['test', 'example.com', 'test@example.com'], + ['test@example.com', 'example.com', 'test@example.com@example.com'], + ]; + } + + /** + * @dataProvider getCloudIdProvider + * + * @param string $user + * @param string $remote + * @param string $id + */ + public function testGetCloudId($user, $remote, $id) { + $cloudId = $this->cloudIdManager->getCloudId($user, $remote); + + $this->assertEquals($id, $cloudId->getId()); + } +} diff --git a/tests/lib/Federation/CloudIdTest.php b/tests/lib/Federation/CloudIdTest.php new file mode 100644 index 00000000000..7a6e841fb34 --- /dev/null +++ b/tests/lib/Federation/CloudIdTest.php @@ -0,0 +1,46 @@ +<?php +/** + * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> + * + * @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\Federation; + +use OC\Federation\CloudId; +use Test\TestCase; + +class CloudIdTest extends TestCase { + public function testGetDisplayCloudIdProvider() { + return [ + ['test@example.com', 'test@example.com'], + ['test@http://example.com', 'test@example.com'], + ['test@https://example.com', 'test@example.com'], + ]; + } + + /** + * @dataProvider testGetDisplayCloudIdProvider + * + * @param string $id + * @param string $display + */ + public function testGetDisplayCloudId($id, $display) { + $cloudId = new CloudId($id, '', ''); + $this->assertEquals($display, $cloudId->getDisplayId()); + } +} diff --git a/tests/lib/Lockdown/Filesystem/NullStorageTest.php b/tests/lib/Lockdown/Filesystem/NullStorageTest.php index dc99eb4c03a..c6faf325cd4 100644 --- a/tests/lib/Lockdown/Filesystem/NullStorageTest.php +++ b/tests/lib/Lockdown/Filesystem/NullStorageTest.php @@ -27,6 +27,7 @@ use Icewind\Streams\IteratorDirectory; use OC\ForbiddenException; use OC\Lockdown\Filesystem\NullCache; use OC\Lockdown\Filesystem\NullStorage; +use OC\Files\FileInfo; use OCP\Files\Storage; use Test\TestCase; @@ -182,7 +183,7 @@ class NullStorageTest extends TestCase { } public function testFree_space() { - $this->assertSame(0, $this->storage->free_space('foo')); + $this->assertSame(FileInfo::SPACE_UNKNOWN, $this->storage->free_space('foo')); } public function testTouch() { diff --git a/tests/lib/UpdaterTest.php b/tests/lib/UpdaterTest.php index 80c7c28cd68..afa0635768d 100644 --- a/tests/lib/UpdaterTest.php +++ b/tests/lib/UpdaterTest.php @@ -57,92 +57,31 @@ class UpdaterTest extends TestCase { } /** - * @param string $baseUrl - * @return string - */ - private function buildUpdateUrl($baseUrl) { - return $baseUrl . '?version='.implode('x', \OCP\Util::getVersion()).'xinstalledatxlastupdatedatx'.\OC_Util::getChannel().'xx'; - } - - /** * @return array */ public function versionCompatibilityTestData() { return [ - ['1', '2', '1', true], - ['2', '2', '2', true], - ['6.0.5.0', '6.0.6.0', '5.0', true], - ['5.0.6.0', '7.0.4.0', '6.0', false], - // allow upgrading within the same major release - ['8.0.0.0', '8.0.0.0', '8.0', true], - ['8.0.0.0', '8.0.0.4', '8.0', true], - ['8.0.0.0', '8.0.1.0', '8.0', true], - ['8.0.0.0', '8.0.2.0', '8.0', true], - // does not allow downgrading within the same major release - ['8.0.1.0', '8.0.0.0', '8.0', false], - ['8.0.2.0', '8.0.1.0', '8.0', false], - ['8.0.0.4', '8.0.0.0', '8.0', false], - // allows upgrading within the patch version - ['8.0.0.0', '8.0.0.1', '8.0', true], - ['8.0.0.0', '8.0.0.2', '8.0', true], - // does not allow downgrading within the same major release - ['8.0.0.1', '8.0.0.0', '8.0', false], - ['8.0.0.2', '8.0.0.0', '8.0', false], - // allow upgrading to the next major release - ['8.0.0.0', '8.1.0.0', '8.0', true], - ['8.0.0.0', '8.1.1.0', '8.0', true], - ['8.0.0.0', '8.1.1.5', '8.0', true], - ['8.0.0.2', '8.1.1.5', '8.0', true], - ['8.1.0.0', '8.2.0.0', '8.1', true], - ['8.1.0.2', '8.2.0.4', '8.1', true], - ['8.1.0.5', '8.2.0.1', '8.1', true], - ['8.1.0.0', '8.2.1.0', '8.1', true], - ['8.1.0.2', '8.2.1.5', '8.1', true], - ['8.1.0.5', '8.2.1.1', '8.1', true], - // does not allow downgrading to the previous major release - ['8.1.0.0', '8.0.0.0', '7.0', false], - ['8.1.1.0', '8.0.0.0', '7.0', false], - // does not allow skipping major releases - ['8.0.0.0', '8.2.0.0', '8.1', false], - ['8.0.0.0', '8.2.1.0', '8.1', false], - ['8.0.0.0', '9.0.1.0', '8.2', false], - ['8.0.0.0', '10.0.0.0', '9.3', false], - // allows updating to the next major release - ['8.2.0.0', '9.0.0.0', '8.2', true], - ['8.2.0.0', '9.0.0.0', '8.2', true], - ['8.2.0.0', '9.0.1.0', '8.2', true], - ['8.2.0.0', '9.0.1.1', '8.2', true], - ['8.2.0.2', '9.0.1.1', '8.2', true], - ['8.2.2.0', '9.0.1.0', '8.2', true], - ['8.2.2.2', '9.0.1.1', '8.2', true], - ['9.0.0.0', '9.1.0.0', '9.0', true], - ['9.0.0.0', '9.1.0.2', '9.0', true], - ['9.0.0.2', '9.1.0.1', '9.0', true], - ['9.1.0.0', '9.2.0.0', '9.1', true], - ['9.2.0.0', '9.3.0.0', '9.2', true], - ['9.3.0.0', '10.0.0.0', '9.3', true], - // does not allow updating to the next major release (first number) - ['9.0.0.0', '8.2.0.0', '8.1', false], - // other cases - ['8.0.0.0', '8.1.5.0', '8.0', true], - ['8.2.0.0', '9.0.0.0', '8.2', true], - ['8.2.0.0', '9.1.0.0', '9.0', false], - ['9.0.0.0', '8.1.0.0', '8.0', false], - ['9.0.0.0', '8.0.0.0', '7.0', false], - ['9.1.0.0', '8.0.0.0', '7.0', false], - ['8.2.0.0', '8.1.0.0', '8.0', false], - - // With debug enabled - ['8.0.0.0', '8.2.0.0', '8.1', false, true], - ['8.1.0.0', '8.2.0.0', '8.1', true, true], - ['8.2.0.1', '8.2.0.1', '8.1', true, true], - ['8.3.0.0', '8.2.0.0', '8.1', true, true], + // Upgrade with invalid version + ['9.1.1.13', '11.0.2.25', ['nextcloud' => ['11.0' => true]], false], + ['10.0.1.13', '11.0.2.25', ['nextcloud' => ['11.0' => true]], false], + // Upgrad with valid version + ['11.0.1.13', '11.0.2.25', ['nextcloud' => ['11.0' => true]], true], + // Downgrade with valid version + ['11.0.2.25', '11.0.1.13', ['nextcloud' => ['11.0' => true]], false], + ['11.0.2.25', '11.0.1.13', ['nextcloud' => ['11.0' => true]], true, true], + // Downgrade with invalid version + ['11.0.2.25', '10.0.1.13', ['nextcloud' => ['10.0' => true]], false], + ['11.0.2.25', '10.0.1.13', ['nextcloud' => ['10.0' => true]], false, true], - // Downgrade of maintenance - ['9.0.53.0', '9.0.4.0', '8.1', false, false, 'nextcloud'], - // with vendor switch - ['9.0.53.0', '9.0.4.0', '8.1', true, false, ''], - ['9.0.53.0', '9.0.4.0', '8.1', true, false, 'owncloud'], + // Migration with unknown vendor + ['9.1.1.13', '11.0.2.25', ['nextcloud' => ['9.1' => true]], false, false, 'owncloud'], + ['9.1.1.13', '11.0.2.25', ['nextcloud' => ['9.1' => true]], false, true, 'owncloud'], + // Migration with unsupported vendor version + ['9.1.1.13', '11.0.2.25', ['owncloud' => ['10.0' => true]], false, false, 'owncloud'], + ['9.1.1.13', '11.0.2.25', ['owncloud' => ['10.0' => true]], false, true, 'owncloud'], + // Migration with valid vendor version + ['9.1.1.13', '11.0.2.25', ['owncloud' => ['9.1' => true]], true, false, 'owncloud'], + ['9.1.1.13', '11.0.2.25', ['owncloud' => ['9.1' => true]], true, true, 'owncloud'], ]; } @@ -151,12 +90,12 @@ class UpdaterTest extends TestCase { * * @param string $oldVersion * @param string $newVersion - * @param string $allowedVersion + * @param array $allowedVersions * @param bool $result * @param bool $debug * @param string $vendor */ - public function testIsUpgradePossible($oldVersion, $newVersion, $allowedVersion, $result, $debug = false, $vendor = 'nextcloud') { + public function testIsUpgradePossible($oldVersion, $newVersion, $allowedVersions, $result, $debug = false, $vendor = 'nextcloud') { $this->config->expects($this->any()) ->method('getSystemValue') ->with('debug', false) @@ -166,7 +105,7 @@ class UpdaterTest extends TestCase { ->with('core', 'vendor', '') ->willReturn($vendor); - $this->assertSame($result, $this->updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersion)); + $this->assertSame($result, $this->updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersions)); } public function testSetSkip3rdPartyAppsDisable() { diff --git a/version.php b/version.php index 90f4e65055a..3d8abb5f2f4 100644 --- a/version.php +++ b/version.php @@ -31,7 +31,15 @@ $OC_Version = array(12, 0, 0, 12); // The human readable string $OC_VersionString = '12.0 alpha'; -$OC_VersionCanBeUpgradedFrom = array(11); +$OC_VersionCanBeUpgradedFrom = [ + 'nextcloud' => [ + '11.0' => true, + '12.0' => true, + ], + 'owncloud' => [ + '10.0' => true, + ], +]; // default Nextcloud channel $OC_Channel = 'git'; |