diff options
138 files changed, 2683 insertions, 218 deletions
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 3afef530e7a..d31851fe17e 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ <name>WebDAV</name> <summary>WebDAV endpoint</summary> <description>WebDAV endpoint</description> - <version>1.5.0</version> + <version>1.5.2</version> <licence>agpl</licence> <author>owncloud.org</author> <namespace>DAV</namespace> @@ -19,6 +19,10 @@ <nextcloud min-version="14" max-version="14" /> </dependencies> + <background-jobs> + <job>OCA\DAV\BackgroundJob\CleanupDirectLinksJob</job> + </background-jobs> + <repair-steps> <post-migration> <step>OCA\DAV\Migration\FixBirthdayCalendarComponent</step> diff --git a/apps/dav/appinfo/routes.php b/apps/dav/appinfo/routes.php index e6785bfd4e6..2aaeda98964 100644 --- a/apps/dav/appinfo/routes.php +++ b/apps/dav/appinfo/routes.php @@ -25,5 +25,8 @@ return [ 'routes' => [ ['name' => 'birthday_calendar#enable', 'url' => '/enableBirthdayCalendar', 'verb' => 'POST'], ['name' => 'birthday_calendar#disable', 'url' => '/disableBirthdayCalendar', 'verb' => 'POST'], - ] + ], + 'ocs' => [ + ['name' => 'direct#getUrl', 'url' => '/api/v1/direct', 'verb' => 'POST'], + ], ]; diff --git a/apps/dav/appinfo/v2/direct.php b/apps/dav/appinfo/v2/direct.php new file mode 100644 index 00000000000..3762a628303 --- /dev/null +++ b/apps/dav/appinfo/v2/direct.php @@ -0,0 +1,47 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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/>. + * + */ + +// no php execution timeout for webdav +if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { + @set_time_limit(0); +} +ignore_user_abort(true); + +// Turn off output buffering to prevent memory problems +\OC_Util::obEnd(); + +$requestUri = \OC::$server->getRequest()->getRequestUri(); + +$serverFactory = new \OCA\DAV\Direct\ServerFactory(\OC::$server->getConfig()); +$server = $serverFactory->createServer( + $baseuri, + $requestUri, + \OC::$server->getRootFolder(), + \OC::$server->query(\OCA\DAV\Db\DirectMapper::class), + \OC::$server->query(\OCP\AppFramework\Utility\ITimeFactory::class), + \OC::$server->getBruteForceThrottler(), + \OC::$server->getRequest() +); + +$server->exec(); diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 0bf6b25751e..50689568ebb 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -11,6 +11,7 @@ return array( 'OCA\\DAV\\Avatars\\AvatarHome' => $baseDir . '/../lib/Avatars/AvatarHome.php', 'OCA\\DAV\\Avatars\\AvatarNode' => $baseDir . '/../lib/Avatars/AvatarNode.php', 'OCA\\DAV\\Avatars\\RootCollection' => $baseDir . '/../lib/Avatars/RootCollection.php', + 'OCA\\DAV\\BackgroundJob\\CleanupDirectLinksJob' => $baseDir . '/../lib/BackgroundJob/CleanupDirectLinksJob.php', 'OCA\\DAV\\BackgroundJob\\GenerateBirthdayCalendarBackgroundJob' => $baseDir . '/../lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php', 'OCA\\DAV\\CalDAV\\Activity\\Backend' => $baseDir . '/../lib/CalDAV/Activity/Backend.php', 'OCA\\DAV\\CalDAV\\Activity\\Filter\\Calendar' => $baseDir . '/../lib/CalDAV/Activity/Filter/Calendar.php', @@ -109,6 +110,7 @@ return array( 'OCA\\DAV\\Connector\\Sabre\\TagList' => $baseDir . '/../lib/Connector/Sabre/TagList.php', 'OCA\\DAV\\Connector\\Sabre\\TagsPlugin' => $baseDir . '/../lib/Connector/Sabre/TagsPlugin.php', 'OCA\\DAV\\Controller\\BirthdayCalendarController' => $baseDir . '/../lib/Controller/BirthdayCalendarController.php', + 'OCA\\DAV\\Controller\\DirectController' => $baseDir . '/../lib/Controller/DirectController.php', 'OCA\\DAV\\DAV\\CustomPropertiesBackend' => $baseDir . '/../lib/DAV/CustomPropertiesBackend.php', 'OCA\\DAV\\DAV\\GroupPrincipalBackend' => $baseDir . '/../lib/DAV/GroupPrincipalBackend.php', 'OCA\\DAV\\DAV\\PublicAuth' => $baseDir . '/../lib/DAV/PublicAuth.php', @@ -118,6 +120,12 @@ return array( 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite' => $baseDir . '/../lib/DAV/Sharing/Xml/Invite.php', 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest' => $baseDir . '/../lib/DAV/Sharing/Xml/ShareRequest.php', 'OCA\\DAV\\DAV\\SystemPrincipalBackend' => $baseDir . '/../lib/DAV/SystemPrincipalBackend.php', + 'OCA\\DAV\\Db\\Direct' => $baseDir . '/../lib/Db/Direct.php', + 'OCA\\DAV\\Db\\DirectMapper' => $baseDir . '/../lib/Db/DirectMapper.php', + 'OCA\\DAV\\Direct\\DirectFile' => $baseDir . '/../lib/Direct/DirectFile.php', + 'OCA\\DAV\\Direct\\DirectHome' => $baseDir . '/../lib/Direct/DirectHome.php', + 'OCA\\DAV\\Direct\\Server' => $baseDir . '/../lib/Direct/Server.php', + 'OCA\\DAV\\Direct\\ServerFactory' => $baseDir . '/../lib/Direct/ServerFactory.php', 'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => $baseDir . '/../lib/Files/BrowserErrorPagePlugin.php', 'OCA\\DAV\\Files\\FileSearchBackend' => $baseDir . '/../lib/Files/FileSearchBackend.php', 'OCA\\DAV\\Files\\FilesHome' => $baseDir . '/../lib/Files/FilesHome.php', @@ -133,6 +141,7 @@ return array( 'OCA\\DAV\\Migration\\Version1004Date20170919104507' => $baseDir . '/../lib/Migration/Version1004Date20170919104507.php', 'OCA\\DAV\\Migration\\Version1004Date20170924124212' => $baseDir . '/../lib/Migration/Version1004Date20170924124212.php', 'OCA\\DAV\\Migration\\Version1004Date20170926103422' => $baseDir . '/../lib/Migration/Version1004Date20170926103422.php', + 'OCA\\DAV\\Migration\\Version1005Date20180413093149' => $baseDir . '/../lib/Migration/Version1005Date20180413093149.php', 'OCA\\DAV\\RootCollection' => $baseDir . '/../lib/RootCollection.php', 'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 4be9b759695..760ca3426f7 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -26,6 +26,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Avatars\\AvatarHome' => __DIR__ . '/..' . '/../lib/Avatars/AvatarHome.php', 'OCA\\DAV\\Avatars\\AvatarNode' => __DIR__ . '/..' . '/../lib/Avatars/AvatarNode.php', 'OCA\\DAV\\Avatars\\RootCollection' => __DIR__ . '/..' . '/../lib/Avatars/RootCollection.php', + 'OCA\\DAV\\BackgroundJob\\CleanupDirectLinksJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/CleanupDirectLinksJob.php', 'OCA\\DAV\\BackgroundJob\\GenerateBirthdayCalendarBackgroundJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php', 'OCA\\DAV\\CalDAV\\Activity\\Backend' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Backend.php', 'OCA\\DAV\\CalDAV\\Activity\\Filter\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Filter/Calendar.php', @@ -124,6 +125,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Connector\\Sabre\\TagList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagList.php', 'OCA\\DAV\\Connector\\Sabre\\TagsPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagsPlugin.php', 'OCA\\DAV\\Controller\\BirthdayCalendarController' => __DIR__ . '/..' . '/../lib/Controller/BirthdayCalendarController.php', + 'OCA\\DAV\\Controller\\DirectController' => __DIR__ . '/..' . '/../lib/Controller/DirectController.php', 'OCA\\DAV\\DAV\\CustomPropertiesBackend' => __DIR__ . '/..' . '/../lib/DAV/CustomPropertiesBackend.php', 'OCA\\DAV\\DAV\\GroupPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/GroupPrincipalBackend.php', 'OCA\\DAV\\DAV\\PublicAuth' => __DIR__ . '/..' . '/../lib/DAV/PublicAuth.php', @@ -133,6 +135,12 @@ class ComposerStaticInitDAV 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite' => __DIR__ . '/..' . '/../lib/DAV/Sharing/Xml/Invite.php', 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest' => __DIR__ . '/..' . '/../lib/DAV/Sharing/Xml/ShareRequest.php', 'OCA\\DAV\\DAV\\SystemPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/SystemPrincipalBackend.php', + 'OCA\\DAV\\Db\\Direct' => __DIR__ . '/..' . '/../lib/Db/Direct.php', + 'OCA\\DAV\\Db\\DirectMapper' => __DIR__ . '/..' . '/../lib/Db/DirectMapper.php', + 'OCA\\DAV\\Direct\\DirectFile' => __DIR__ . '/..' . '/../lib/Direct/DirectFile.php', + 'OCA\\DAV\\Direct\\DirectHome' => __DIR__ . '/..' . '/../lib/Direct/DirectHome.php', + 'OCA\\DAV\\Direct\\Server' => __DIR__ . '/..' . '/../lib/Direct/Server.php', + 'OCA\\DAV\\Direct\\ServerFactory' => __DIR__ . '/..' . '/../lib/Direct/ServerFactory.php', 'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/BrowserErrorPagePlugin.php', 'OCA\\DAV\\Files\\FileSearchBackend' => __DIR__ . '/..' . '/../lib/Files/FileSearchBackend.php', 'OCA\\DAV\\Files\\FilesHome' => __DIR__ . '/..' . '/../lib/Files/FilesHome.php', @@ -148,6 +156,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Migration\\Version1004Date20170919104507' => __DIR__ . '/..' . '/../lib/Migration/Version1004Date20170919104507.php', 'OCA\\DAV\\Migration\\Version1004Date20170924124212' => __DIR__ . '/..' . '/../lib/Migration/Version1004Date20170924124212.php', 'OCA\\DAV\\Migration\\Version1004Date20170926103422' => __DIR__ . '/..' . '/../lib/Migration/Version1004Date20170926103422.php', + 'OCA\\DAV\\Migration\\Version1005Date20180413093149' => __DIR__ . '/..' . '/../lib/Migration/Version1005Date20180413093149.php', 'OCA\\DAV\\RootCollection' => __DIR__ . '/..' . '/../lib/RootCollection.php', 'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php', diff --git a/apps/dav/l10n/pt_BR.js b/apps/dav/l10n/pt_BR.js index b98acb4faa8..75346f3aacb 100644 --- a/apps/dav/l10n/pt_BR.js +++ b/apps/dav/l10n/pt_BR.js @@ -64,6 +64,6 @@ OC.L10N.register( "Please make sure to properly set up the email settings above." : "Certifique-se de configurar corretamente o email acima.", "Automatically generate a birthday calendar" : "Gerar um calendário de aniversários automaticamente", "Birthday calendars will be generated by a background job." : "Os calendários de aniversários serão gerados na retaguarda.", - "Hence they will not be available immediately after enabling but will show up after some time." : "Portanto, eles não estarão disponíveis imediatamente ao habilitar, mas após algum tempo." + "Hence they will not be available immediately after enabling but will show up after some time." : "Portanto, eles não estarão disponíveis imediatamente ao habilitar mas após algum tempo." }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/dav/l10n/pt_BR.json b/apps/dav/l10n/pt_BR.json index e3797e17f27..f773ee0d93f 100644 --- a/apps/dav/l10n/pt_BR.json +++ b/apps/dav/l10n/pt_BR.json @@ -62,6 +62,6 @@ "Please make sure to properly set up the email settings above." : "Certifique-se de configurar corretamente o email acima.", "Automatically generate a birthday calendar" : "Gerar um calendário de aniversários automaticamente", "Birthday calendars will be generated by a background job." : "Os calendários de aniversários serão gerados na retaguarda.", - "Hence they will not be available immediately after enabling but will show up after some time." : "Portanto, eles não estarão disponíveis imediatamente ao habilitar, mas após algum tempo." + "Hence they will not be available immediately after enabling but will show up after some time." : "Portanto, eles não estarão disponíveis imediatamente ao habilitar mas após algum tempo." },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php b/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php new file mode 100644 index 00000000000..ba1049071ad --- /dev/null +++ b/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php @@ -0,0 +1,50 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\BackgroundJob; + +use OC\BackgroundJob\TimedJob; +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Utility\ITimeFactory; + +class CleanupDirectLinksJob extends TimedJob { + /** @var ITimeFactory */ + private $timeFactory; + + /** @var DirectMapper */ + private $mapper; + + public function __construct(ITimeFactory $timeFactory, DirectMapper $mapper) { + $this->setInterval(60*60*24); + + $this->timeFactory = $timeFactory; + $this->mapper = $mapper; + } + + protected function run($argument) { + // Delete all shares expired 24 hours ago + $this->mapper->deleteExpired($this->timeFactory->getTime() - 60*60*24); + } + +} diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php index fd237b604a9..9e78d21a39d 100644 --- a/apps/dav/lib/Connector/Sabre/Node.php +++ b/apps/dav/lib/Connector/Sabre/Node.php @@ -272,7 +272,7 @@ abstract class Node implements \Sabre\DAV\INode { $mountpointpath = substr($mountpointpath, 0, -1); } - if ($mountpointpath === $this->info->getPath()) { + if (!$mountpoint->getOption('readonly', false) && $mountpointpath === $this->info->getPath()) { $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE; } } diff --git a/apps/dav/lib/Controller/DirectController.php b/apps/dav/lib/Controller/DirectController.php new file mode 100644 index 00000000000..2a14e4db2c7 --- /dev/null +++ b/apps/dav/lib/Controller/DirectController.php @@ -0,0 +1,113 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Controller; + +use OCA\DAV\Db\Direct; +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSBadRequestException; +use OCP\AppFramework\OCS\OCSNotFoundException; +use OCP\AppFramework\OCSController; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Files\File; +use OCP\Files\IRootFolder; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\Security\ISecureRandom; + +class DirectController extends OCSController { + + /** @var IRootFolder */ + private $rootFolder; + + /** @var string */ + private $userId; + + /** @var DirectMapper */ + private $mapper; + + /** @var ISecureRandom */ + private $random; + + /** @var ITimeFactory */ + private $timeFactory; + + /** @var IURLGenerator */ + private $urlGenerator; + + + public function __construct(string $appName, + IRequest $request, + IRootFolder $rootFolder, + string $userId, + DirectMapper $mapper, + ISecureRandom $random, + ITimeFactory $timeFactory, + IURLGenerator $urlGenerator) { + parent::__construct($appName, $request); + + $this->rootFolder = $rootFolder; + $this->userId = $userId; + $this->mapper = $mapper; + $this->random = $random; + $this->timeFactory = $timeFactory; + $this->urlGenerator = $urlGenerator; + } + + /** + * @NoAdminRequired + */ + public function getUrl(int $fileId): DataResponse { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + + $files = $userFolder->getById($fileId); + + if ($files === []) { + throw new OCSNotFoundException(); + } + + $file = array_shift($files); + if (!($file instanceof File)) { + throw new OCSBadRequestException('Direct download only works for files'); + } + + //TODO: at some point we should use the directdownlaod function of storages + $direct = new Direct(); + $direct->setUserId($this->userId); + $direct->setFileId($fileId); + + $token = $this->random->generate(60, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS); + $direct->setToken($token); + $direct->setExpiration($this->timeFactory->getTime() + 60 * 60 * 8); + + $this->mapper->insert($direct); + + $url = $this->urlGenerator->getAbsoluteURL('remote.php/direct/'.$token); + + return new DataResponse([ + 'url' => $url, + ]); + } +} diff --git a/apps/dav/lib/Db/Direct.php b/apps/dav/lib/Db/Direct.php new file mode 100644 index 00000000000..ef588b1ec3a --- /dev/null +++ b/apps/dav/lib/Db/Direct.php @@ -0,0 +1,58 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Db; + +use OCP\AppFramework\Db\Entity; + +/** + * @method string getUserId() + * @method void setUserId(string $userId) + * @method int getFileId() + * @method void setFileId(int $fileId) + * @method string getToken() + * @method void setToken(string $token) + * @method int getExpiration() + * @method void setExpiration(int $expiration) + */ +class Direct extends Entity { + /** @var string */ + protected $userId; + + /** @var int */ + protected $fileId; + + /** @var string */ + protected $token; + + /** @var int */ + protected $expiration; + + public function __construct() { + $this->addType('userId', 'string'); + $this->addType('fileId', 'int'); + $this->addType('token', 'string'); + $this->addType('expiration', 'int'); + } +} diff --git a/apps/dav/lib/Db/DirectMapper.php b/apps/dav/lib/Db/DirectMapper.php new file mode 100644 index 00000000000..d0db4b82879 --- /dev/null +++ b/apps/dav/lib/Db/DirectMapper.php @@ -0,0 +1,72 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Db; + +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\Mapper; +use OCP\IDBConnection; + +class DirectMapper extends Mapper { + + public function __construct(IDBConnection $db) { + parent::__construct($db, 'directlink', Direct::class); + } + + /** + * @param string $token + * @return Direct + * @throws DoesNotExistException + */ + public function getByToken(string $token): Direct { + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from('directlink') + ->where( + $qb->expr()->eq('token', $qb->createNamedParameter($token)) + ); + + $cursor = $qb->execute(); + $data = $cursor->fetch(); + $cursor->closeCursor(); + + if ($data === false) { + throw new DoesNotExistException('Direct link with token does not exist'); + } + + return Direct::fromRow($data); + } + + public function deleteExpired(int $expiration) { + $qb = $this->db->getQueryBuilder(); + + $qb->delete('directlink') + ->where( + $qb->expr()->lt('expiration', $qb->createNamedParameter($expiration)) + ); + + $qb->execute(); + } +} diff --git a/apps/dav/lib/Direct/DirectFile.php b/apps/dav/lib/Direct/DirectFile.php new file mode 100644 index 00000000000..947352c5148 --- /dev/null +++ b/apps/dav/lib/Direct/DirectFile.php @@ -0,0 +1,110 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Direct; + +use OCA\DAV\Db\Direct; +use OCP\Files\File; +use OCP\Files\IRootFolder; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\IFile; + +class DirectFile implements IFile { + /** @var Direct */ + private $direct; + + /** @var IRootFolder */ + private $rootFolder; + + /** @var File */ + private $file; + + public function __construct(Direct $direct, IRootFolder $rootFolder) { + $this->direct = $direct; + $this->rootFolder = $rootFolder; + } + + public function put($data) { + throw new Forbidden(); + } + + public function get() { + $this->getFile(); + + return $this->file->fopen('rb'); + } + + public function getContentType() { + $this->getFile(); + + return $this->file->getMimeType(); + } + + public function getETag() { + $this->getFile(); + + return $this->file->getEtag(); + } + + public function getSize() { + $this->getFile(); + + return $this->file->getSize(); + } + + public function delete() { + throw new Forbidden(); + } + + public function getName() { + return $this->direct->getToken(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified() { + $this->getFile(); + + return $this->file->getMTime(); + } + + private function getFile() { + if ($this->file === null) { + $userFolder = $this->rootFolder->getUserFolder($this->direct->getUserId()); + $files = $userFolder->getById($this->direct->getFileId()); + + if ($files === []) { + throw new NotFound(); + } + + $this->file = array_shift($files); + } + + return $this->file; + } + +} diff --git a/apps/dav/lib/Direct/DirectHome.php b/apps/dav/lib/Direct/DirectHome.php new file mode 100644 index 00000000000..e0246c83de9 --- /dev/null +++ b/apps/dav/lib/Direct/DirectHome.php @@ -0,0 +1,118 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Direct; + +use OC\Security\Bruteforce\Throttler; +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Files\IRootFolder; +use OCP\IRequest; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class DirectHome implements ICollection { + + /** @var IRootFolder */ + private $rootFolder; + + /** @var DirectMapper */ + private $mapper; + + /** @var ITimeFactory */ + private $timeFactory; + + /** @var Throttler */ + private $throttler; + + /** @var IRequest */ + private $request; + + public function __construct(IRootFolder $rootFolder, + DirectMapper $mapper, + ITimeFactory $timeFactory, + Throttler $throttler, + IRequest $request) { + $this->rootFolder = $rootFolder; + $this->mapper = $mapper; + $this->timeFactory = $timeFactory; + $this->throttler = $throttler; + $this->request = $request; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name): DirectFile { + try { + $direct = $this->mapper->getByToken($name); + + // Expired + if ($direct->getExpiration() < $this->timeFactory->getTime()) { + throw new NotFound(); + } + + return new DirectFile($direct, $this->rootFolder); + } catch (DoesNotExistException $e) { + // Since the token space is so huge only throttle on non exsisting token + $this->throttler->registerAttempt('directlink', $this->request->getRemoteAddress()); + $this->throttler->sleepDelay($this->request->getRemoteAddress(), 'directlink'); + + throw new NotFound(); + } + } + + public function getChildren() { + throw new MethodNotAllowed('Listing members of this collection is disabled'); + } + + public function childExists($name): bool { + return false; + } + + public function delete() { + throw new Forbidden(); + } + + public function getName(): string { + return 'direct'; + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return 0; + } + +} diff --git a/apps/dav/lib/Direct/Server.php b/apps/dav/lib/Direct/Server.php new file mode 100644 index 00000000000..373dc2dca50 --- /dev/null +++ b/apps/dav/lib/Direct/Server.php @@ -0,0 +1,33 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Direct; + +class Server extends \Sabre\DAV\Server { + public function __construct($treeOrNode = null) { + parent::__construct($treeOrNode); + self::$exposeVersion = false; + $this->enablePropfindDepthInfinityf = false; + } +} diff --git a/apps/dav/lib/Direct/ServerFactory.php b/apps/dav/lib/Direct/ServerFactory.php new file mode 100644 index 00000000000..618f6889fd0 --- /dev/null +++ b/apps/dav/lib/Direct/ServerFactory.php @@ -0,0 +1,61 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Direct; + +use OC\Security\Bruteforce\Throttler; +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Files\IRootFolder; +use OCP\IConfig; +use OCP\IRequest; + +class ServerFactory { + /** @var IConfig */ + private $config; + + public function __construct(IConfig $config) { + $this->config = $config; + } + + public function createServer(string $baseURI, + string $requestURI, + IRootFolder $rootFolder, + DirectMapper $mapper, + ITimeFactory $timeFactory, + Throttler $throttler, + IRequest $request): Server { + $home = new DirectHome($rootFolder, $mapper, $timeFactory, $throttler, $request); + $server = new Server($home); + + $server->httpRequest->setUrl($requestURI); + $server->setBaseUri($baseURI); + + $server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin($this->config)); + + return $server; + + + } +} diff --git a/apps/dav/lib/Migration/Version1005Date20180413093149.php b/apps/dav/lib/Migration/Version1005Date20180413093149.php new file mode 100644 index 00000000000..cd6aeca6b48 --- /dev/null +++ b/apps/dav/lib/Migration/Version1005Date20180413093149.php @@ -0,0 +1,80 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Migration; + +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +class Version1005Date20180413093149 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if (!$schema->hasTable('directlink')) { + $table = $schema->createTable('directlink'); + + $table->addColumn('id',Type::BIGINT, [ + 'autoincrement' => true, + 'notnull' => true, + 'length' => 11, + 'unsigned' => true, + ]); + $table->addColumn('user_id', Type::STRING, [ + 'notnull' => false, + 'length' => 64, + ]); + $table->addColumn('file_id', Type::BIGINT, [ + 'notnull' => true, + 'length' => 11, + 'unsigned' => true, + ]); + $table->addColumn('token', Type::STRING, [ + 'notnull' => false, + 'length' => 60, + ]); + $table->addColumn('expiration', Type::BIGINT, [ + 'notnull' => true, + 'length' => 11, + 'unsigned' => true, + ]); + + $table->setPrimaryKey(['id'], 'directlink_id_idx'); + $table->addIndex(['token'], 'directlink_token_idx'); + $table->addIndex(['expiration'], 'directlink_expiration_idx'); + + return $schema; + } + } +} diff --git a/apps/dav/tests/unit/Controller/DirectControllerTest.php b/apps/dav/tests/unit/Controller/DirectControllerTest.php new file mode 100644 index 00000000000..e52c67ac30c --- /dev/null +++ b/apps/dav/tests/unit/Controller/DirectControllerTest.php @@ -0,0 +1,155 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Tests\Unit\DAV\Controller; + +use OCA\DAV\Controller\DirectController; +use OCA\DAV\Db\Direct; +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSBadRequestException; +use OCP\AppFramework\OCS\OCSNotFoundException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\Security\ISecureRandom; +use Test\TestCase; + +class DirectControllerTest extends TestCase { + + /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ + private $rootFolder; + + /** @var DirectMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $directMapper; + + /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + private $random; + + /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */ + private $timeFactory; + + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + + /** @var DirectController */ + private $controller; + + public function setUp() { + parent::setUp(); + + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->directMapper = $this->createMock(DirectMapper::class); + $this->random = $this->createMock(ISecureRandom::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + + $this->controller = new DirectController( + 'dav', + $this->createMock(IRequest::class), + $this->rootFolder, + 'awesomeUser', + $this->directMapper, + $this->random, + $this->timeFactory, + $this->urlGenerator + ); + } + + public function testGetUrlNonExistingFileId() { + $userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with('awesomeUser') + ->willReturn($userFolder); + + $userFolder->method('getById') + ->with(101) + ->willReturn([]); + + $this->expectException(OCSNotFoundException::class); + $this->controller->getUrl(101); + } + + public function testGetUrlForFolder() { + $userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with('awesomeUser') + ->willReturn($userFolder); + + $folder = $this->createMock(Folder::class); + + $userFolder->method('getById') + ->with(101) + ->willReturn([$folder]); + + $this->expectException(OCSBadRequestException::class); + $this->controller->getUrl(101); + } + + public function testGetUrlValid() { + $userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with('awesomeUser') + ->willReturn($userFolder); + + $file = $this->createMock(File::class); + + $this->timeFactory->method('getTime') + ->willReturn(42); + + $userFolder->method('getById') + ->with(101) + ->willReturn([$file]); + + $this->random->method('generate') + ->with( + 60, + ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS + )->willReturn('superduperlongtoken'); + + $this->directMapper->expects($this->once()) + ->method('insert') + ->willReturnCallback(function (Direct $direct) { + $this->assertSame('awesomeUser', $direct->getUserId()); + $this->assertSame(101, $direct->getFileId()); + $this->assertSame('superduperlongtoken', $direct->getToken()); + $this->assertSame(42 + 60*60*8, $direct->getExpiration()); + }); + + $this->urlGenerator->method('getAbsoluteURL') + ->willReturnCallback(function(string $url) { + return 'https://my.nextcloud/'.$url; + }); + + $result = $this->controller->getUrl(101); + + $this->assertInstanceOf(DataResponse::class, $result); + $this->assertSame([ + 'url' => 'https://my.nextcloud/remote.php/direct/superduperlongtoken', + ], $result->getData()); + } +} diff --git a/apps/dav/tests/unit/Direct/DirectFileTest.php b/apps/dav/tests/unit/Direct/DirectFileTest.php new file mode 100644 index 00000000000..2203e7c7686 --- /dev/null +++ b/apps/dav/tests/unit/Direct/DirectFileTest.php @@ -0,0 +1,132 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Tests\Unit\Direct; + +use OCA\DAV\Db\Direct; +use OCA\DAV\Direct\DirectFile; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use Sabre\DAV\Exception\Forbidden; +use Test\TestCase; + +class DirectFileTest extends TestCase { + + /** @var Direct */ + private $direct; + + /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ + private $rootFolder; + + /** @var Folder|\PHPUnit_Framework_MockObject_MockObject */ + private $userFolder; + + /** @var File|\PHPUnit_Framework_MockObject_MockObject */ + private $file; + + /** @var DirectFile */ + private $directFile; + + public function setUp() { + parent::setUp(); + + $this->direct = Direct::fromParams([ + 'userId' => 'directUser', + 'token' => 'directToken', + 'fileId' => 42, + ]); + + $this->rootFolder = $this->createMock(IRootFolder::class); + + $this->userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with('directUser') + ->willReturn($this->userFolder); + + $this->file = $this->createMock(File::class); + $this->userFolder->method('getById') + ->with(42) + ->willReturn([$this->file]); + + $this->directFile = new DirectFile($this->direct, $this->rootFolder); + } + + public function testPut() { + $this->expectException(Forbidden::class); + + $this->directFile->put('foo'); + } + + public function testGet() { + $this->file->expects($this->once()) + ->method('fopen') + ->with('rb'); + $this->directFile->get(); + } + + public function testGetContentType() { + $this->file->method('getMimeType') + ->willReturn('direct/type'); + + $this->assertSame('direct/type', $this->directFile->getContentType()); + } + + public function testGetETag() { + $this->file->method('getEtag') + ->willReturn('directEtag'); + + $this->assertSame('directEtag', $this->directFile->getETag()); + } + + public function testGetSize() { + $this->file->method('getSize') + ->willReturn(42); + + $this->assertSame(42, $this->directFile->getSize()); + } + + public function testDelete() { + $this->expectException(Forbidden::class); + + $this->directFile->delete(); + } + + public function testGetName() { + $this->assertSame('directToken', $this->directFile->getName()); + } + + public function testSetName() { + $this->expectException(Forbidden::class); + + $this->directFile->setName('foobar'); + } + + public function testGetLastModified() { + $this->file->method('getMTime') + ->willReturn(42); + + $this->assertSame(42, $this->directFile->getLastModified()); + } +} diff --git a/apps/dav/tests/unit/Direct/DirectHomeTest.php b/apps/dav/tests/unit/Direct/DirectHomeTest.php new file mode 100644 index 00000000000..dbbfb1fe1ff --- /dev/null +++ b/apps/dav/tests/unit/Direct/DirectHomeTest.php @@ -0,0 +1,182 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\DAV\Tests\Unit\Direct; + +use OC\Security\Bruteforce\Throttler; +use OCA\DAV\Db\Direct; +use OCA\DAV\Db\DirectMapper; +use OCA\DAV\Direct\DirectFile; +use OCA\DAV\Direct\DirectHome; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Files\IRootFolder; +use OCP\IRequest; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\Exception\NotFound; +use Test\TestCase; + +class DirectHomeTest extends TestCase { + + /** @var DirectMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $directMapper; + + /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ + private $rootFolder; + + /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */ + private $timeFactory; + + /** @var Throttler|\PHPUnit_Framework_MockObject_MockObject */ + private $throttler; + + /** @var IRequest */ + private $request; + + /** @var DirectHome */ + private $directHome; + + public function setUp() { + parent::setUp(); + + $this->directMapper = $this->createMock(DirectMapper::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->throttler = $this->createMock(Throttler::class); + $this->request = $this->createMock(IRequest::class); + + $this->timeFactory->method('getTime') + ->willReturn(42); + + $this->request->method('getRemoteAddress') + ->willReturn('1.2.3.4'); + + $this->directHome = new DirectHome( + $this->rootFolder, + $this->directMapper, + $this->timeFactory, + $this->throttler, + $this->request + ); + } + + public function testCreateFile() { + $this->expectException(Forbidden::class); + + $this->directHome->createFile('foo', 'bar'); + } + + public function testCreateDirectory() { + $this->expectException(Forbidden::class); + + $this->directHome->createDirectory('foo'); + } + + public function testGetChildren() { + $this->expectException(MethodNotAllowed::class); + + $this->directHome->getChildren(); + } + + public function testChildExists() { + $this->assertFalse($this->directHome->childExists('foo')); + } + + public function testDelete() { + $this->expectException(Forbidden::class); + + $this->directHome->delete(); + } + + public function testGetName() { + $this->assertSame('direct', $this->directHome->getName()); + } + + public function testSetName() { + $this->expectException(Forbidden::class); + + $this->directHome->setName('foo'); + } + + public function testGetLastModified() { + $this->assertSame(0, $this->directHome->getLastModified()); + } + + public function testGetChildValid() { + $direct = Direct::fromParams([ + 'expiration' => 100, + ]); + + $this->directMapper->method('getByToken') + ->with('longtoken') + ->willReturn($direct); + + $this->throttler->expects($this->never()) + ->method($this->anything()); + + $result = $this->directHome->getChild('longtoken'); + $this->assertInstanceOf(DirectFile::class, $result); + } + + public function testGetChildExpired() { + $direct = Direct::fromParams([ + 'expiration' => 41, + ]); + + $this->directMapper->method('getByToken') + ->with('longtoken') + ->willReturn($direct); + + $this->throttler->expects($this->never()) + ->method($this->anything()); + + $this->expectException(NotFound::class); + + $this->directHome->getChild('longtoken'); + } + + public function testGetChildInvalid() { + $this->directMapper->method('getByToken') + ->with('longtoken') + ->willThrowException(new DoesNotExistException('not found')); + + $this->throttler->expects($this->once()) + ->method('registerAttempt') + ->with( + 'directlink', + '1.2.3.4' + ); + $this->throttler->expects($this->once()) + ->method('sleepDelay') + ->with( + '1.2.3.4', + 'directlink' + ); + + $this->expectException(NotFound::class); + + $this->directHome->getChild('longtoken'); + } +} diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index ffe1e972071..983348397d1 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -48,6 +48,12 @@ var MOUNT_OPTIONS_DROPDOWN_TEMPLATE = ' <label for="mountOptionsEncoding">{{mountOptionsEncodingLabel}}</label>'+ ' </span>'+ ' </li>'+ + ' <li class="optionRow">' + + ' <span class="menuitem">' + + ' <input id="mountOptionsReadOnly" class="checkbox" name="readonly" type="checkbox" value="true"/>' + + ' <label for="mountOptionsReadOnly">{{t "files_external" "Read only"}}</label>' + + ' </span>' + + ' </li>' + ' </ul>'+ '</div>'; @@ -916,7 +922,8 @@ MountConfigListView.prototype = _.extend({ 'previews': true, 'enable_sharing': false, 'filesystem_check_changes': 1, - 'encoding_compatibility': false + 'encoding_compatibility': false, + 'readonly': false, })); } @@ -1303,7 +1310,8 @@ MountConfigListView.prototype = _.extend({ 'previews', 'filesystem_check_changes', 'enable_sharing', - 'encoding_compatibility' + 'encoding_compatibility', + 'readonly' ]; if (this._encryptionEnabled) { visibleOptions.push('encrypt'); diff --git a/apps/files_external/l10n/pl.js b/apps/files_external/l10n/pl.js index 9b7dce2396a..5d83036fa53 100644 --- a/apps/files_external/l10n/pl.js +++ b/apps/files_external/l10n/pl.js @@ -14,6 +14,7 @@ OC.L10N.register( "(group)" : "(grupa)", "Compatibility with Mac NFD encoding (slow)" : "Zgodność z kodowaniem Mac NFD (powolny)", "Admin defined" : "Zdefiniowane przez Administratora", + "Are you sure you want to delete this external storage?" : "Czy na pewno chcesz usunąć zewnętrzny magazyn?", "Delete storage?" : "Usunąć magazyn?", "Saved" : "Zapisano", "Saving..." : "Zapisywanie...", @@ -55,8 +56,10 @@ OC.L10N.register( "OAuth2" : "OAuth2", "Client ID" : "ID klienta", "Client secret" : "Hasło klienta", + "OpenStack v2" : "OpenStack v2", "Tenant name" : "Nazwa dzierżawcy", "Identity endpoint URL" : "Adres końcówki identyfikującej", + "OpenStack v3" : "OpenStack v3", "Domain" : "Domena", "Rackspace" : "Rackspace", "API key" : "Klucz API", @@ -98,6 +101,8 @@ OC.L10N.register( "The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "Obsługa cURL w PHP jest wyłączona lub nie jest zainstalowana. Zamontowanie %s jest niemożliwe. Proszę poprosić swojego administratora systemu, żeby ją zainstalował.", "The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "Obsługa FTP w PHP jest wyłączona lub nie jest zainstalowana. Zamontowanie %s jest niemożliwe. Proszę poprosić swojego administratora systemu, żeby ją zainstalował.", "\"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "\"%s\" nie jest zainstalowane. Zamontowanie %s jest niemożliwe. Proszę poprosić swojego administratora systemu, żeby dokonał instalacji.", + "External storage support" : "Wsparcie zewnętrznego magazynu", + "No external storage configured or you don't have the permission to configure them" : "Brak magazynów zewnętrznych lub nie masz uprawnień do ich konfiguracji", "Name" : "Nazwa", "Storage type" : "Typ magazynu", "Scope" : "Zakres", @@ -112,6 +117,7 @@ OC.L10N.register( "Authentication" : "Poświadczenie", "Configuration" : "Konfiguracja", "Available for" : "Dostępne dla", + "Click to recheck the configuration" : "Kliknij aby ponownie sprawdzić konfigurację", "Add storage" : "Dodaj zewnętrzne magazyny", "Advanced settings" : "Ustawienia zaawansowane", "Delete" : "Usuń", diff --git a/apps/files_external/l10n/pl.json b/apps/files_external/l10n/pl.json index cb509d198ab..8c20d980390 100644 --- a/apps/files_external/l10n/pl.json +++ b/apps/files_external/l10n/pl.json @@ -12,6 +12,7 @@ "(group)" : "(grupa)", "Compatibility with Mac NFD encoding (slow)" : "Zgodność z kodowaniem Mac NFD (powolny)", "Admin defined" : "Zdefiniowane przez Administratora", + "Are you sure you want to delete this external storage?" : "Czy na pewno chcesz usunąć zewnętrzny magazyn?", "Delete storage?" : "Usunąć magazyn?", "Saved" : "Zapisano", "Saving..." : "Zapisywanie...", @@ -53,8 +54,10 @@ "OAuth2" : "OAuth2", "Client ID" : "ID klienta", "Client secret" : "Hasło klienta", + "OpenStack v2" : "OpenStack v2", "Tenant name" : "Nazwa dzierżawcy", "Identity endpoint URL" : "Adres końcówki identyfikującej", + "OpenStack v3" : "OpenStack v3", "Domain" : "Domena", "Rackspace" : "Rackspace", "API key" : "Klucz API", @@ -96,6 +99,8 @@ "The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "Obsługa cURL w PHP jest wyłączona lub nie jest zainstalowana. Zamontowanie %s jest niemożliwe. Proszę poprosić swojego administratora systemu, żeby ją zainstalował.", "The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "Obsługa FTP w PHP jest wyłączona lub nie jest zainstalowana. Zamontowanie %s jest niemożliwe. Proszę poprosić swojego administratora systemu, żeby ją zainstalował.", "\"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "\"%s\" nie jest zainstalowane. Zamontowanie %s jest niemożliwe. Proszę poprosić swojego administratora systemu, żeby dokonał instalacji.", + "External storage support" : "Wsparcie zewnętrznego magazynu", + "No external storage configured or you don't have the permission to configure them" : "Brak magazynów zewnętrznych lub nie masz uprawnień do ich konfiguracji", "Name" : "Nazwa", "Storage type" : "Typ magazynu", "Scope" : "Zakres", @@ -110,6 +115,7 @@ "Authentication" : "Poświadczenie", "Configuration" : "Konfiguracja", "Available for" : "Dostępne dla", + "Click to recheck the configuration" : "Kliknij aby ponownie sprawdzić konfigurację", "Add storage" : "Dodaj zewnętrzne magazyny", "Advanced settings" : "Ustawienia zaawansowane", "Delete" : "Usuń", diff --git a/apps/files_external/lib/Command/ListCommand.php b/apps/files_external/lib/Command/ListCommand.php index efb2669e281..89bdcf5e5d6 100644 --- a/apps/files_external/lib/Command/ListCommand.php +++ b/apps/files_external/lib/Command/ListCommand.php @@ -192,7 +192,8 @@ class ListCommand extends Base { 'previews' => true, 'filesystem_check_changes' => 1, 'enable_sharing' => false, - 'encoding_compatibility' => false + 'encoding_compatibility' => false, + 'readonly' => false, ]; $rows = array_map(function (StorageConfig $config) use ($userId, $defaultMountOptions, $full) { $storageConfig = $config->getBackendOptions(); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 895be719ab4..236faf37d6d 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -12,6 +12,7 @@ $l->t("Check for changes"); $l->t("Never"); $l->t("Once every direct access"); + $l->t('Read only'); script('files_external', 'settings'); style('files_external', 'settings'); diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js index 56bdcff8345..fbbb341c307 100644 --- a/apps/files_external/tests/js/settingsSpec.js +++ b/apps/files_external/tests/js/settingsSpec.js @@ -376,7 +376,8 @@ describe('OCA.External.Settings tests', function() { previews: true, enable_sharing: false, filesystem_check_changes: 0, - encoding_compatibility: false + encoding_compatibility: false, + readonly: false }); }); }); diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index b2715912d3b..22513e1b470 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -254,20 +254,7 @@ * @returns {String} */ getSharePermissions: function(fileData) { - var sharePermissions = fileData.permissions; - if (fileData.mountType && fileData.mountType === "external-root"){ - // for external storages we can't use the permissions of the mountpoint - // instead we show all permissions and only use the share permissions from the mountpoint to handle resharing - sharePermissions = sharePermissions | (OC.PERMISSION_ALL & ~OC.PERMISSION_SHARE); - } - if (fileData.type === 'file') { - // files can't be shared with delete permissions - sharePermissions = sharePermissions & ~OC.PERMISSION_DELETE; - - // create permissions don't mean anything for files - sharePermissions = sharePermissions & ~OC.PERMISSION_CREATE; - } - return sharePermissions; + return fileData.sharePermissions; } }; })(); diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js index 1b9091270ae..f3fbe2bbfaf 100644 --- a/apps/files_sharing/l10n/pl.js +++ b/apps/files_sharing/l10n/pl.js @@ -92,6 +92,7 @@ OC.L10N.register( "Direct link" : "Bezpośredni link", "Add to your Nextcloud" : "Dodaj do swojego Nextcloud", "Share API is disabled" : "API udostępniania jest wyłączone", + "File sharing" : "Udostępnianie plików", "This share is password-protected" : "Udostępniony folder chroniony jest hasłem", "The password is wrong. Try again." : "To hasło jest niewłaściwe. Spróbuj ponownie.", "Password" : "Hasło", diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json index bc055c72673..447dac53d84 100644 --- a/apps/files_sharing/l10n/pl.json +++ b/apps/files_sharing/l10n/pl.json @@ -90,6 +90,7 @@ "Direct link" : "Bezpośredni link", "Add to your Nextcloud" : "Dodaj do swojego Nextcloud", "Share API is disabled" : "API udostępniania jest wyłączone", + "File sharing" : "Udostępnianie plików", "This share is password-protected" : "Udostępniony folder chroniony jest hasłem", "The password is wrong. Try again." : "To hasło jest niewłaściwe. Spróbuj ponownie.", "Password" : "Hasło", diff --git a/apps/files_sharing/l10n/pt_BR.js b/apps/files_sharing/l10n/pt_BR.js index f4d4d728b84..e0ae7d6da45 100644 --- a/apps/files_sharing/l10n/pt_BR.js +++ b/apps/files_sharing/l10n/pt_BR.js @@ -5,7 +5,7 @@ OC.L10N.register( "Shared with others" : "Compartilhado com outros", "Shared by link" : "Compartilhado por link", "Nothing shared with you yet" : "Nada foi compartilhado!", - "Files and folders others share with you will show up here" : "Arquivos e pastas que outras pessoas compartilham com você, serão exibidos aqui.", + "Files and folders others share with you will show up here" : "Arquivos e pastas que outras pessoas compartilham com você serão exibidos aqui.", "Nothing shared yet" : "Você ainda não compartilhou nada!", "Files and folders you share will show up here" : "Arquivos e pastas que você compartilhar serão exibidos aqui.", "No shared links" : "Nenhum link compartilhado", @@ -61,7 +61,7 @@ OC.L10N.register( "{actor} removed {user} from {file}" : "{actor} excluiu {user} de {file}", "{actor} shared {file} with you" : "{actor} compartilhou {file} com você", "{actor} removed you from {file}" : "{actor} excluiu você de {file}", - "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Um arquivo ou pasta compartilhado por e-mail ou por link publico foi <strong>baixado</strong>", + "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Um arquivo ou pasta compartilhado por email ou por link publico foi <strong>baixado</strong>", "A file or folder was shared from <strong>another server</strong>" : "Um arquivo ou pasta foi compartilhado a partir de <strong>outro servidor</strong>", "A file or folder has been <strong>shared</strong>" : "Um arquivo ou pasta foi <strong>compartilhado</strong> ", "Wrong share ID, share doesn't exist" : "ID de compartilhamento errado, o compartilhamento não existe", @@ -98,8 +98,8 @@ OC.L10N.register( "Password" : "Senha", "No entries found in this folder" : "Nenhuma entrada foi encontrada nesta pasta", "Name" : "Nome", - "Share time" : "Data de compartilhamento", - "Expiration date" : "Data de expiração", + "Share time" : "Compartilhamento", + "Expiration date" : "Expiração", "Sorry, this link doesn’t seem to work anymore." : "Desculpe, este link parece não funcionar mais.", "Reasons might be:" : "As razões podem ser:", "the item was removed" : "o item foi removido", diff --git a/apps/files_sharing/l10n/pt_BR.json b/apps/files_sharing/l10n/pt_BR.json index b512e5d3a6c..483681b40cd 100644 --- a/apps/files_sharing/l10n/pt_BR.json +++ b/apps/files_sharing/l10n/pt_BR.json @@ -3,7 +3,7 @@ "Shared with others" : "Compartilhado com outros", "Shared by link" : "Compartilhado por link", "Nothing shared with you yet" : "Nada foi compartilhado!", - "Files and folders others share with you will show up here" : "Arquivos e pastas que outras pessoas compartilham com você, serão exibidos aqui.", + "Files and folders others share with you will show up here" : "Arquivos e pastas que outras pessoas compartilham com você serão exibidos aqui.", "Nothing shared yet" : "Você ainda não compartilhou nada!", "Files and folders you share will show up here" : "Arquivos e pastas que você compartilhar serão exibidos aqui.", "No shared links" : "Nenhum link compartilhado", @@ -59,7 +59,7 @@ "{actor} removed {user} from {file}" : "{actor} excluiu {user} de {file}", "{actor} shared {file} with you" : "{actor} compartilhou {file} com você", "{actor} removed you from {file}" : "{actor} excluiu você de {file}", - "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Um arquivo ou pasta compartilhado por e-mail ou por link publico foi <strong>baixado</strong>", + "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Um arquivo ou pasta compartilhado por email ou por link publico foi <strong>baixado</strong>", "A file or folder was shared from <strong>another server</strong>" : "Um arquivo ou pasta foi compartilhado a partir de <strong>outro servidor</strong>", "A file or folder has been <strong>shared</strong>" : "Um arquivo ou pasta foi <strong>compartilhado</strong> ", "Wrong share ID, share doesn't exist" : "ID de compartilhamento errado, o compartilhamento não existe", @@ -96,8 +96,8 @@ "Password" : "Senha", "No entries found in this folder" : "Nenhuma entrada foi encontrada nesta pasta", "Name" : "Nome", - "Share time" : "Data de compartilhamento", - "Expiration date" : "Data de expiração", + "Share time" : "Compartilhamento", + "Expiration date" : "Expiração", "Sorry, this link doesn’t seem to work anymore." : "Desculpe, este link parece não funcionar mais.", "Reasons might be:" : "As razões podem ser:", "the item was removed" : "o item foi removido", diff --git a/apps/files_sharing/tests/js/sharedfilelistSpec.js b/apps/files_sharing/tests/js/sharedfilelistSpec.js index 903234947bd..0897e9c956d 100644 --- a/apps/files_sharing/tests/js/sharedfilelistSpec.js +++ b/apps/files_sharing/tests/js/sharedfilelistSpec.js @@ -723,14 +723,16 @@ describe('OCA.Sharing.FileList tests', function() { mimetype: 'text/plain', size: 12, permissions: OC.PERMISSION_READ, + sharePermissions: OC.PERMISSION_READ, etag: 'abc', shareOwner: 'User One', recipients: 'User Two', - mountType: 'external-root' + mountType: 'external-root', + sharePermissions: OC.PERMISSION_READ, }]); $tr = fileList.$el.find('tr:first'); - expect(parseInt($tr.attr('data-share-permissions'), 10)).toEqual(OC.PERMISSION_ALL - OC.PERMISSION_SHARE); + expect(parseInt($tr.attr('data-share-permissions'), 10)).toEqual(OC.PERMISSION_READ); }); it('external storage root folder reshare', function () { @@ -744,14 +746,16 @@ describe('OCA.Sharing.FileList tests', function() { mimetype: 'text/plain', size: 12, permissions: OC.PERMISSION_READ + OC.PERMISSION_SHARE, + sharePermissions: OC.PERMISSION_READ + OC.PERMISSION_SHARE, etag: 'abc', shareOwner: 'User One', recipients: 'User Two', - mountType: 'external-root' + mountType: 'external-root', + sharePermissions: OC.PERMISSION_READ | OC.PERMISSION_SHARE, }]); $tr = fileList.$el.find('tr:first'); - expect(parseInt($tr.attr('data-share-permissions'), 10)).toEqual(OC.PERMISSION_ALL); + expect(parseInt($tr.attr('data-share-permissions'), 10)).toEqual(OC.PERMISSION_READ + OC.PERMISSION_SHARE); }); it('external storage root folder file', function () { @@ -765,6 +769,7 @@ describe('OCA.Sharing.FileList tests', function() { mimetype: 'text/plain', size: 12, permissions: OC.PERMISSION_READ, + sharePermissions: OC.PERMISSION_READ, etag: 'abc', shareOwner: 'User One', recipients: 'User Two', @@ -773,7 +778,7 @@ describe('OCA.Sharing.FileList tests', function() { $tr = fileList.$el.find('tr:first'); expect(parseInt($tr.attr('data-share-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_SHARE - OC.PERMISSION_DELETE - OC.PERMISSION_CREATE); + .toEqual(OC.PERMISSION_READ); }); }); }); diff --git a/apps/files_trashbin/appinfo/info.xml b/apps/files_trashbin/appinfo/info.xml index 585e61fe1e8..4ca60c0e269 100644 --- a/apps/files_trashbin/appinfo/info.xml +++ b/apps/files_trashbin/appinfo/info.xml @@ -9,13 +9,14 @@ This application enables users to restore files that were deleted from the syste To prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation. </description> - <version>1.4.0</version> + <version>1.4.1</version> <licence>agpl</licence> <author>Bjoern Schiessle</author> <namespace>Files_Trashbin</namespace> <default_enable/> <types> <filesystem/> + <dav/> </types> <documentation> <user>user-trashbin</user> @@ -34,4 +35,13 @@ To prevent a user from running out of disk space, the Deleted files app will not <command>OCA\Files_Trashbin\Command\CleanUp</command> <command>OCA\Files_Trashbin\Command\ExpireTrash</command> </commands> + + <sabre> + <collections> + <collection>OCA\Files_Trashbin\Sabre\RootCollection</collection> + </collections> + <plugins> + <plugin>OCA\Files_Trashbin\Sabre\PropfindPlugin</plugin> + </plugins> + </sabre> </info> diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index 2e58c7b1c6c..3713de530c6 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -18,6 +18,16 @@ return array( 'OCA\\Files_Trashbin\\Expiration' => $baseDir . '/../lib/Expiration.php', 'OCA\\Files_Trashbin\\Helper' => $baseDir . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => $baseDir . '/../lib/Hooks.php', + 'OCA\\Files_Trashbin\\Sabre\\ITrash' => $baseDir . '/../lib/Sabre/ITrash.php', + 'OCA\\Files_Trashbin\\Sabre\\PropfindPlugin' => $baseDir . '/../lib/Sabre/PropfindPlugin.php', + 'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => $baseDir . '/../lib/Sabre/RootCollection.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => $baseDir . '/../lib/Sabre/TrashFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolder' => $baseDir . '/../lib/Sabre/TrashFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFile' => $baseDir . '/../lib/Sabre/TrashFolderFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFolder' => $baseDir . '/../lib/Sabre/TrashFolderFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashHome' => $baseDir . '/../lib/Sabre/TrashHome.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashRoot' => $baseDir . '/../lib/Sabre/TrashRoot.php', 'OCA\\Files_Trashbin\\Storage' => $baseDir . '/../lib/Storage.php', 'OCA\\Files_Trashbin\\Trashbin' => $baseDir . '/../lib/Trashbin.php', ); diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index 01520e2d14d..b00778741b3 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -33,6 +33,16 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php', 'OCA\\Files_Trashbin\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php', + 'OCA\\Files_Trashbin\\Sabre\\ITrash' => __DIR__ . '/..' . '/../lib/Sabre/ITrash.php', + 'OCA\\Files_Trashbin\\Sabre\\PropfindPlugin' => __DIR__ . '/..' . '/../lib/Sabre/PropfindPlugin.php', + 'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => __DIR__ . '/..' . '/../lib/Sabre/RootCollection.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolder' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolderFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFolder' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolderFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashHome' => __DIR__ . '/..' . '/../lib/Sabre/TrashHome.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashRoot' => __DIR__ . '/..' . '/../lib/Sabre/TrashRoot.php', 'OCA\\Files_Trashbin\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php', 'OCA\\Files_Trashbin\\Trashbin' => __DIR__ . '/..' . '/../lib/Trashbin.php', ); diff --git a/apps/files_trashbin/l10n/pt_BR.js b/apps/files_trashbin/l10n/pt_BR.js index d937db7b513..fa410eca940 100644 --- a/apps/files_trashbin/l10n/pt_BR.js +++ b/apps/files_trashbin/l10n/pt_BR.js @@ -12,7 +12,7 @@ OC.L10N.register( "This directory is unavailable, please check the logs or contact the administrator" : "Este diretório não está disponível. Por favor verifique os logs ou contacte o administrador", "restored" : "restaurado", "No deleted files" : "Nenhum arquivo excluído", - "You will be able to recover deleted files from here" : "Você pode recuperar arquivos excluídos deste local", + "You will be able to recover deleted files from here" : "Você pode recuperar arquivos excluídos neste local", "No entries found in this folder" : "Nenhuma entrada foi encontrada nesta pasta", "Select all" : "Selecionar tudo", "Name" : "Nome", diff --git a/apps/files_trashbin/l10n/pt_BR.json b/apps/files_trashbin/l10n/pt_BR.json index 21fd0324355..138affd4ada 100644 --- a/apps/files_trashbin/l10n/pt_BR.json +++ b/apps/files_trashbin/l10n/pt_BR.json @@ -10,7 +10,7 @@ "This directory is unavailable, please check the logs or contact the administrator" : "Este diretório não está disponível. Por favor verifique os logs ou contacte o administrador", "restored" : "restaurado", "No deleted files" : "Nenhum arquivo excluído", - "You will be able to recover deleted files from here" : "Você pode recuperar arquivos excluídos deste local", + "You will be able to recover deleted files from here" : "Você pode recuperar arquivos excluídos neste local", "No entries found in this folder" : "Nenhuma entrada foi encontrada nesta pasta", "Select all" : "Selecionar tudo", "Name" : "Nome", diff --git a/apps/files_trashbin/lib/AppInfo/Application.php b/apps/files_trashbin/lib/AppInfo/Application.php index e9d4e6ecc1d..ea27c8c16ea 100644 --- a/apps/files_trashbin/lib/AppInfo/Application.php +++ b/apps/files_trashbin/lib/AppInfo/Application.php @@ -23,6 +23,7 @@ namespace OCA\Files_Trashbin\AppInfo; +use OCA\DAV\Connector\Sabre\Principal; use OCP\AppFramework\App; use OCA\Files_Trashbin\Expiration; use OCP\AppFramework\Utility\ITimeFactory; @@ -47,5 +48,17 @@ class Application extends App { $c->query(ITimeFactory::class) ); }); + + /* + * Register $principalBackend for the DAV collection + */ + $container->registerService('principalBackend', function () { + return new Principal( + \OC::$server->getUserManager(), + \OC::$server->getGroupManager(), + \OC::$server->getShareManager(), + \OC::$server->getUserSession() + ); + }); } } diff --git a/apps/files_trashbin/lib/Sabre/ITrash.php b/apps/files_trashbin/lib/Sabre/ITrash.php new file mode 100644 index 00000000000..b0ff2b1570a --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/ITrash.php @@ -0,0 +1,32 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +interface ITrash { + public function restore(): bool; + + public function getFilename(): string; + + public function getOriginalLocation(): string; +} diff --git a/apps/files_trashbin/lib/Sabre/PropfindPlugin.php b/apps/files_trashbin/lib/Sabre/PropfindPlugin.php new file mode 100644 index 00000000000..e50ee08590a --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/PropfindPlugin.php @@ -0,0 +1,64 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\INode; +use Sabre\DAV\PropFind; +use Sabre\DAV\Server; +use Sabre\DAV\ServerPlugin; + +class PropfindPlugin extends ServerPlugin { + + const TRASHBIN_FILENAME = '{http://nextcloud.org/ns}trashbin-filename'; + const TRASHBIN_ORIGINAL_LOCATION = '{http://nextcloud.org/ns}trashbin-original-location'; + + /** @var Server */ + private $server; + + public function __construct() { + } + + public function initialize(Server $server) { + $this->server = $server; + + $this->server->on('propFind', [$this, 'propFind']); + } + + + public function propFind(PropFind $propFind, INode $node) { + if (!($node instanceof ITrash)) { + return; + } + + $propFind->handle(self::TRASHBIN_FILENAME, function() use ($node) { + return $node->getFilename(); + }); + + $propFind->handle(self::TRASHBIN_ORIGINAL_LOCATION, function() use ($node) { + return $node->getOriginalLocation(); + }); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/RestoreFolder.php b/apps/files_trashbin/lib/Sabre/RestoreFolder.php new file mode 100644 index 00000000000..04f23db0ed4 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/RestoreFolder.php @@ -0,0 +1,86 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\ICollection; +use Sabre\DAV\IMoveTarget; +use Sabre\DAV\INode; + + +class RestoreFolder implements ICollection, IMoveTarget { + + /** @var string */ + protected $userId; + + public function __construct(string $userId) { + $this->userId = $userId; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name) { + return null; + } + + public function delete() { + throw new Forbidden(); + } + + public function getName() { + return 'restore'; + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return 0; + } + + public function getChildren(): array { + return []; + } + + public function childExists($name): bool { + return false; + } + + public function moveInto($targetName, $sourcePath, INode $sourceNode): bool { + if (!($sourceNode instanceof ITrash)) { + return false; + } + + return $sourceNode->restore(); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/RootCollection.php b/apps/files_trashbin/lib/Sabre/RootCollection.php new file mode 100644 index 00000000000..e425fb448e2 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/RootCollection.php @@ -0,0 +1,59 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\INode; +use Sabre\DAVACL\AbstractPrincipalCollection; +use Sabre\DAVACL\PrincipalBackend; + +class RootCollection extends AbstractPrincipalCollection { + + public function __construct(PrincipalBackend\BackendInterface $principalBackend) { + parent::__construct($principalBackend, 'principals/users'); + } + + /** + * This method returns a node for a principal. + * + * The passed array contains principal information, and is guaranteed to + * at least contain a uri item. Other properties may or may not be + * supplied by the authentication backend. + * + * @param array $principalInfo + * @return INode + */ + public function getChildForPrincipal(array $principalInfo): TrashHome { + list(,$name) = \Sabre\Uri\split($principalInfo['uri']); + $user = \OC::$server->getUserSession()->getUser(); + if (is_null($user) || $name !== $user->getUID()) { + throw new \Sabre\DAV\Exception\Forbidden(); + } + return new TrashHome($principalInfo); + } + + public function getName(): string { + return 'trashbin'; + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFile.php b/apps/files_trashbin/lib/Sabre/TrashFile.php new file mode 100644 index 00000000000..29e7a955623 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFile.php @@ -0,0 +1,91 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\IFile; + +class TrashFile implements IFile, ITrash { + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + public function __construct(string $userId, FileInfo $data) { + $this->userId = $userId; + $this->data = $data; + } + + public function put($data) { + throw new Forbidden(); + } + + public function get() { + return $this->data->getStorage()->fopen($this->data->getInternalPath().'.d'.$this->getLastModified(), 'rb'); + } + + public function getContentType(): string { + return $this->data->getMimetype(); + } + + public function getETag(): string { + return $this->data->getEtag(); + } + + public function getSize(): int { + return $this->data->getSize(); + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified()); + } + + public function getName(): string { + return $this->data->getName() . '.d' . $this->getLastModified(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return $this->data->getMtime(); + } + + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified()); + } + + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->data['extraData']; + } + + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php new file mode 100644 index 00000000000..33236eea262 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php @@ -0,0 +1,120 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class TrashFolder implements ICollection, ITrash { + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + public function __construct(string $root, string $userId, FileInfo $data) { + $this->userId = $userId; + $this->data = $data; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name): ITrash { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + } + return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + } + } + + throw new NotFound(); + } + + public function getChildren(): array { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); + + $children = array_map(function (FileInfo $entry) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + } + return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + }, $entries); + + return $children; + } + + public function childExists($name): bool { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + return true; + } + } + + return false; + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified()); + } + + public function getName(): string { + return $this->data->getName() . '.d' . $this->getLastModified(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return $this->data->getMtime(); + } + + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified()); + } + + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->data['extraData']; + } + + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php new file mode 100644 index 00000000000..95e82d95a6e --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php @@ -0,0 +1,102 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\IFile; + +class TrashFolderFile implements IFile, ITrash { + /** @var string */ + private $root; + + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + /** @var string */ + private $location; + + public function __construct(string $root, + string $userId, + FileInfo $data, + string $location) { + $this->root = $root; + $this->userId = $userId; + $this->data = $data; + $this->location = $location; + } + + public function put($data) { + throw new Forbidden(); + } + + public function get() { + return $this->data->getStorage()->fopen($this->data->getInternalPath(), 'rb'); + } + + public function getContentType(): string { + return $this->data->getMimetype(); + } + + public function getETag(): string { + return $this->data->getEtag(); + } + + public function getSize(): int { + return $this->data->getSize(); + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null); + } + + public function getName(): string { + return $this->data->getName(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return $this->data->getMtime(); + } + + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null); + } + + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->location . '/' . $this->getFilename(); + } + + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php new file mode 100644 index 00000000000..d2923c58916 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php @@ -0,0 +1,133 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class TrashFolderFolder implements ICollection, ITrash { + + /** @var string */ + private $root; + + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + /** @var string */ + private $location; + + public function __construct(string $root, + string $userId, + FileInfo $data, + string $location) { + $this->root = $root; + $this->userId = $userId; + $this->data = $data; + $this->location = $location; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name): ITrash { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolderFolder($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + } + return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + } + } + + throw new NotFound(); + } + + public function getChildren(): array { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); + + $children = array_map(function (FileInfo $entry) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolderFolder($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + } + return new TrashFolderFile($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation()); + }, $entries); + + return $children; + } + + public function childExists($name): bool { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + return true; + } + } + + return false; + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null); + } + + public function getName(): string { + return $this->data->getName(); + + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return $this->data->getMtime(); + } + + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null); + } + + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->location . '/' . $this->getFilename(); + } + + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php new file mode 100644 index 00000000000..d1c50c9c6a3 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashHome.php @@ -0,0 +1,89 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class TrashHome implements ICollection { + + /** @var array */ + private $principalInfo; + + public function __construct(array $principalInfo) { + $this->principalInfo = $principalInfo; + } + + public function delete() { + throw new Forbidden(); + } + + public function getName(): string { + list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']); + return $name; + } + + public function setName($name) { + throw new Forbidden('Permission denied to rename this trashbin'); + } + + public function createFile($name, $data = null) { + throw new Forbidden('Not allowed to create files in the trashbin'); + } + + public function createDirectory($name) { + throw new Forbidden('Not allowed to create folders in the trashbin'); + } + + public function getChild($name) { + list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + + if ($name === 'restore') { + return new RestoreFolder($userId); + } + if ($name === 'trash') { + return new TrashRoot($userId); + } + + throw new NotFound(); + } + + public function getChildren(): array { + list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + + return [ + new RestoreFolder($userId), + new TrashRoot($userId), + ]; + } + + public function childExists($name): bool { + return $name === 'restore' || $name === 'trash'; + } + + public function getLastModified(): int { + return 0; + } +} diff --git a/apps/files_trashbin/lib/Sabre/TrashRoot.php b/apps/files_trashbin/lib/Sabre/TrashRoot.php new file mode 100644 index 00000000000..73b9d44d7e1 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashRoot.php @@ -0,0 +1,103 @@ +<?php +declare(strict_types=1); +/** + * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class TrashRoot implements ICollection { + + /** @var string */ + private $userId; + + public function __construct(string $userId) { + $this->userId = $userId; + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::deleteAll(); + } + + public function getName(): string { + return 'trash'; + } + + public function setName($name) { + throw new Forbidden('Permission denied to rename this trashbin'); + } + + public function createFile($name, $data = null) { + throw new Forbidden('Not allowed to create files in the trashbin'); + } + + public function createDirectory($name) { + throw new Forbidden('Not allowed to create folders in the trashbin'); + } + + public function getChild($name): ITrash { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() . '.d'.$entry->getMtime() === $name) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolder('/', $this->userId, $entry); + } + return new TrashFile($this->userId, $entry); + } + } + + throw new NotFound(); + } + + public function getChildren(): array { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId); + + $children = array_map(function (FileInfo $entry) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolder('/', $this->userId, $entry); + } + return new TrashFile($this->userId, $entry); + }, $entries); + + return $children; + } + + public function childExists($name): bool { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() . '.d'.$entry->getMtime() === $name) { + return true; + } + } + + return false; + } + + public function getLastModified(): int { + return 0; + } +} diff --git a/apps/oauth2/l10n/pt_BR.js b/apps/oauth2/l10n/pt_BR.js index 4cdf0a5f903..c8ebcf56412 100644 --- a/apps/oauth2/l10n/pt_BR.js +++ b/apps/oauth2/l10n/pt_BR.js @@ -3,7 +3,7 @@ OC.L10N.register( { "OAuth 2.0" : "OAuth 2.0", "OAuth 2.0 clients" : "Clientes OAuth 2.0", - "OAuth 2.0 allows external services to request access to %s." : "OAuth 2.0 permite que serviços externos requisitem acesso a %s.", + "OAuth 2.0 allows external services to request access to %s." : "OAuth 2.0 permite que serviços externos solicitem acesso a %s.", "Name" : "Nome", "Redirection URI" : "Redirecionamento URI", "Client Identifier" : "Identificador do Cliente", diff --git a/apps/oauth2/l10n/pt_BR.json b/apps/oauth2/l10n/pt_BR.json index 74f23369db4..3705eb01975 100644 --- a/apps/oauth2/l10n/pt_BR.json +++ b/apps/oauth2/l10n/pt_BR.json @@ -1,7 +1,7 @@ { "translations": { "OAuth 2.0" : "OAuth 2.0", "OAuth 2.0 clients" : "Clientes OAuth 2.0", - "OAuth 2.0 allows external services to request access to %s." : "OAuth 2.0 permite que serviços externos requisitem acesso a %s.", + "OAuth 2.0 allows external services to request access to %s." : "OAuth 2.0 permite que serviços externos solicitem acesso a %s.", "Name" : "Nome", "Redirection URI" : "Redirecionamento URI", "Client Identifier" : "Identificador do Cliente", diff --git a/apps/sharebymail/l10n/de.js b/apps/sharebymail/l10n/de.js index 7456b959727..06f8b94b1a9 100644 --- a/apps/sharebymail/l10n/de.js +++ b/apps/sharebymail/l10n/de.js @@ -29,7 +29,7 @@ OC.L10N.register( "Password to access »%s« shared to you by %s" : "Das Passwort zum Zugriff auf %s wurde durch %s mit Dir geteilt.", "Password to access »%s«" : "Passwort um auf »%s« zu zugreifen", "It is protected with the following password: %s" : "Dies ist mit dem folgendem Passwort geschützt: %s", - "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Du hast »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien die der Administrator von %s vorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund musst Du das Passwort selbst an den Empfänger senden.", + "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Du hast »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien, die der Administrator von %s vorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund musst Du das Passwort selbst an den Empfänger senden.", "Password to access »%s« shared with %s" : "Passwort für den Zugriff auf %s, geteilt mit %s", "This is the password: %s" : "Das Passwort lautet: %s", "You can choose a different password at any time in the share dialog." : "Im Teilen-Dialog kannst Du jederzeit ein anderes Passwort wählen.", diff --git a/apps/sharebymail/l10n/de.json b/apps/sharebymail/l10n/de.json index ebdb263ad8a..379a9d37907 100644 --- a/apps/sharebymail/l10n/de.json +++ b/apps/sharebymail/l10n/de.json @@ -27,7 +27,7 @@ "Password to access »%s« shared to you by %s" : "Das Passwort zum Zugriff auf %s wurde durch %s mit Dir geteilt.", "Password to access »%s«" : "Passwort um auf »%s« zu zugreifen", "It is protected with the following password: %s" : "Dies ist mit dem folgendem Passwort geschützt: %s", - "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Du hast »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien die der Administrator von %s vorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund musst Du das Passwort selbst an den Empfänger senden.", + "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Du hast »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien, die der Administrator von %s vorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund musst Du das Passwort selbst an den Empfänger senden.", "Password to access »%s« shared with %s" : "Passwort für den Zugriff auf %s, geteilt mit %s", "This is the password: %s" : "Das Passwort lautet: %s", "You can choose a different password at any time in the share dialog." : "Im Teilen-Dialog kannst Du jederzeit ein anderes Passwort wählen.", diff --git a/apps/sharebymail/l10n/de_DE.js b/apps/sharebymail/l10n/de_DE.js index b64cd6e801d..5bc2273bb8b 100644 --- a/apps/sharebymail/l10n/de_DE.js +++ b/apps/sharebymail/l10n/de_DE.js @@ -29,7 +29,7 @@ OC.L10N.register( "Password to access »%s« shared to you by %s" : "Das Passwort zum Zugriff auf %s wurde durch %s mit Ihnen geteilt.", "Password to access »%s«" : "Passwort um auf »%s« zu zugreifen", "It is protected with the following password: %s" : "Dies ist mit dem folgendem Passwort geschützt: %s", - "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Sie haben »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien die der Administrator von %svorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund müssen Sie das Passwort selbst an den Empfänger senden.", + "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Sie haben »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien, die der Administrator von %s vorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund müssen Sie das Passwort selbst an den Empfänger senden.", "Password to access »%s« shared with %s" : "Passwort für den Zugriff auf %s, geteilt mit %s", "This is the password: %s" : "Das Passwort lautet: %s", "You can choose a different password at any time in the share dialog." : "Im Teilen-Dialog können Sie jederzeit ein anderes Passwort wählen.", diff --git a/apps/sharebymail/l10n/de_DE.json b/apps/sharebymail/l10n/de_DE.json index ec4c52d3b13..1f08d42d75c 100644 --- a/apps/sharebymail/l10n/de_DE.json +++ b/apps/sharebymail/l10n/de_DE.json @@ -27,7 +27,7 @@ "Password to access »%s« shared to you by %s" : "Das Passwort zum Zugriff auf %s wurde durch %s mit Ihnen geteilt.", "Password to access »%s«" : "Passwort um auf »%s« zu zugreifen", "It is protected with the following password: %s" : "Dies ist mit dem folgendem Passwort geschützt: %s", - "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Sie haben »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien die der Administrator von %svorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund müssen Sie das Passwort selbst an den Empfänger senden.", + "You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient." : "Sie haben »%s« mit %s geteilt. Die Freigabe wurde an den Empfänger gesandt. Aufgrund der Sicherheits-Richtlinien, die der Administrator von %s vorgegeben hat, benötigt jede Freigabe einen Passwortschutz und es ist nicht zulässig, ein Passwort direkt an den Empfänger zu versenden. Aus diesem Grund müssen Sie das Passwort selbst an den Empfänger senden.", "Password to access »%s« shared with %s" : "Passwort für den Zugriff auf %s, geteilt mit %s", "This is the password: %s" : "Das Passwort lautet: %s", "You can choose a different password at any time in the share dialog." : "Im Teilen-Dialog können Sie jederzeit ein anderes Passwort wählen.", diff --git a/apps/sharebymail/l10n/pt_BR.js b/apps/sharebymail/l10n/pt_BR.js index 747d5ea6a81..7c56a3adae9 100644 --- a/apps/sharebymail/l10n/pt_BR.js +++ b/apps/sharebymail/l10n/pt_BR.js @@ -7,25 +7,25 @@ OC.L10N.register( "Shared with {email} by {actor}" : "Compartilhado com {email} por {actor}", "Password for mail share sent to %1$s" : "Senha para o correio compartilhado enviado para %1$s", "Password for mail share sent to {email}" : "Senha para o correio compartilhado enviado para {email}", - "Password for mail share sent to you" : "Senha para o e-mail compartilhado foi enviado para você", - "You shared %1$s with %2$s by mail" : "Você compartilhou %1$s com %2$s por e-mail", - "You shared {file} with {email} by mail" : "Você compartilhou {file} com {email} por e-mail", - "%3$s shared %1$s with %2$s by mail" : "%3$s compartilou %1$s com %2$s por e-mail", - "{actor} shared {file} with {email} by mail" : "{actor} compartilhou {file} com {email} por e-mail", + "Password for mail share sent to you" : "Senha do compartilhamento por email foi enviado para você", + "You shared %1$s with %2$s by mail" : "Você compartilhou %1$s com %2$s por email", + "You shared {file} with {email} by mail" : "Você compartilhou {file} com {email} por email", + "%3$s shared %1$s with %2$s by mail" : "%3$s compartilou %1$s com %2$s por email", + "{actor} shared {file} with {email} by mail" : "{actor} compartilhou {file} com {email} por email", "Password to access %1$s was sent to %2s" : "A senha para acesso %1$s foi enviada para %2s", "Password to access {file} was sent to {email}" : "A senha para acesso {file} foi enviada para {email}", "Password to access %1$s was sent to you" : "A senha para acesso %1$s foi enviada para você", "Password to access {file} was sent to you" : "A senha para acesso {file} foi enviada para você", "Sharing %s failed, this item is already shared with %s" : "O compartilhamento %s falhou, pois este item já está compartilhado com %s", - "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Não pudemos enviar a você a senha auto-gerada. por favor defina um e-mail válido em sua configuração e tente novamente.", - "Failed to send share by email" : "Falha ao enviar compartilhamento via e-mail", + "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Não pudemos enviar a você a senha auto-gerada. por favor defina um email válido em sua configuração e tente novamente.", + "Failed to send share by email" : "Falha ao enviar compartilhamento via email", "%s shared »%s« with you" : "%s compartilhou »%s« com você", "%s shared »%s« with you." : "%s compartilhou »%s« com você.", "Click the button below to open it." : "Clique no botão abaixo para abrí-lo.", "Open »%s«" : "Abrir »%s«", "%s via %s" : "%s via %s", - "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s compartilhou »%s« com você.\nVocê já deve ter recebido um e-mail com um link para acessá-lo.\n", - "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s compartilhou »%s« com você. Você já deve ter recebido um e-mail com um link para acessá-lo.", + "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s compartilhou »%s« com você.\nVocê já deve ter recebido um email com um link para acessá-lo.\n", + "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s compartilhou »%s« com você. Você já deve ter recebido um email com um link para acessá-lo.", "Password to access »%s« shared to you by %s" : "Senha para acessar %s compartilhado com você por %s", "Password to access »%s«" : "Senha para acessar »%s«", "It is protected with the following password: %s" : "Está protegido com a seguinte senha: %s", @@ -34,10 +34,10 @@ OC.L10N.register( "This is the password: %s" : "Essa é a senha: %s", "You can choose a different password at any time in the share dialog." : "Você pode escolher uma senha diferente a qualquer momento no diálogo compartilhamento.", "Could not find share" : "Não foi possível encontrar o compartilhamento", - "Share by mail" : "Compartilhamento por e-mail", - "Allows users to share a personalized link to a file or folder by putting in an email address." : "Permite que os usuários compartilhem um link personalizado para um arquivo ou pasta, inserindo um endereço de e-mail.", - "Send password by mail" : "Enviar senha por e-mail", + "Share by mail" : "Compartilhamento por email", + "Allows users to share a personalized link to a file or folder by putting in an email address." : "Permite que os usuários compartilhem um link personalizado para um arquivo ou pasta, inserindo um endereço de email.", + "Send password by mail" : "Enviar senha por email", "Enforce password protection" : "Reforce a proteção por senha", - "Failed to send share by E-mail" : "Falha ao enviar compartilhamento por e-mail" + "Failed to send share by E-mail" : "Falha ao enviar compartilhamento por email" }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/sharebymail/l10n/pt_BR.json b/apps/sharebymail/l10n/pt_BR.json index 604e02cba4b..2fe879e512c 100644 --- a/apps/sharebymail/l10n/pt_BR.json +++ b/apps/sharebymail/l10n/pt_BR.json @@ -5,25 +5,25 @@ "Shared with {email} by {actor}" : "Compartilhado com {email} por {actor}", "Password for mail share sent to %1$s" : "Senha para o correio compartilhado enviado para %1$s", "Password for mail share sent to {email}" : "Senha para o correio compartilhado enviado para {email}", - "Password for mail share sent to you" : "Senha para o e-mail compartilhado foi enviado para você", - "You shared %1$s with %2$s by mail" : "Você compartilhou %1$s com %2$s por e-mail", - "You shared {file} with {email} by mail" : "Você compartilhou {file} com {email} por e-mail", - "%3$s shared %1$s with %2$s by mail" : "%3$s compartilou %1$s com %2$s por e-mail", - "{actor} shared {file} with {email} by mail" : "{actor} compartilhou {file} com {email} por e-mail", + "Password for mail share sent to you" : "Senha do compartilhamento por email foi enviado para você", + "You shared %1$s with %2$s by mail" : "Você compartilhou %1$s com %2$s por email", + "You shared {file} with {email} by mail" : "Você compartilhou {file} com {email} por email", + "%3$s shared %1$s with %2$s by mail" : "%3$s compartilou %1$s com %2$s por email", + "{actor} shared {file} with {email} by mail" : "{actor} compartilhou {file} com {email} por email", "Password to access %1$s was sent to %2s" : "A senha para acesso %1$s foi enviada para %2s", "Password to access {file} was sent to {email}" : "A senha para acesso {file} foi enviada para {email}", "Password to access %1$s was sent to you" : "A senha para acesso %1$s foi enviada para você", "Password to access {file} was sent to you" : "A senha para acesso {file} foi enviada para você", "Sharing %s failed, this item is already shared with %s" : "O compartilhamento %s falhou, pois este item já está compartilhado com %s", - "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Não pudemos enviar a você a senha auto-gerada. por favor defina um e-mail válido em sua configuração e tente novamente.", - "Failed to send share by email" : "Falha ao enviar compartilhamento via e-mail", + "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Não pudemos enviar a você a senha auto-gerada. por favor defina um email válido em sua configuração e tente novamente.", + "Failed to send share by email" : "Falha ao enviar compartilhamento via email", "%s shared »%s« with you" : "%s compartilhou »%s« com você", "%s shared »%s« with you." : "%s compartilhou »%s« com você.", "Click the button below to open it." : "Clique no botão abaixo para abrí-lo.", "Open »%s«" : "Abrir »%s«", "%s via %s" : "%s via %s", - "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s compartilhou »%s« com você.\nVocê já deve ter recebido um e-mail com um link para acessá-lo.\n", - "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s compartilhou »%s« com você. Você já deve ter recebido um e-mail com um link para acessá-lo.", + "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s compartilhou »%s« com você.\nVocê já deve ter recebido um email com um link para acessá-lo.\n", + "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s compartilhou »%s« com você. Você já deve ter recebido um email com um link para acessá-lo.", "Password to access »%s« shared to you by %s" : "Senha para acessar %s compartilhado com você por %s", "Password to access »%s«" : "Senha para acessar »%s«", "It is protected with the following password: %s" : "Está protegido com a seguinte senha: %s", @@ -32,10 +32,10 @@ "This is the password: %s" : "Essa é a senha: %s", "You can choose a different password at any time in the share dialog." : "Você pode escolher uma senha diferente a qualquer momento no diálogo compartilhamento.", "Could not find share" : "Não foi possível encontrar o compartilhamento", - "Share by mail" : "Compartilhamento por e-mail", - "Allows users to share a personalized link to a file or folder by putting in an email address." : "Permite que os usuários compartilhem um link personalizado para um arquivo ou pasta, inserindo um endereço de e-mail.", - "Send password by mail" : "Enviar senha por e-mail", + "Share by mail" : "Compartilhamento por email", + "Allows users to share a personalized link to a file or folder by putting in an email address." : "Permite que os usuários compartilhem um link personalizado para um arquivo ou pasta, inserindo um endereço de email.", + "Send password by mail" : "Enviar senha por email", "Enforce password protection" : "Reforce a proteção por senha", - "Failed to send share by E-mail" : "Falha ao enviar compartilhamento por e-mail" + "Failed to send share by E-mail" : "Falha ao enviar compartilhamento por email" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/apps/theming/l10n/de.js b/apps/theming/l10n/de.js index 6435fb7bead..d9a7bbf84ae 100644 --- a/apps/theming/l10n/de.js +++ b/apps/theming/l10n/de.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Anmelde-Bild", "Upload new login background" : "Neuen Anmelde-Hintergrund hochladen", "Remove background image" : "Entferne Hintergrundbild", + "Advanced options" : "Erweiterte Optionen", + "Header logo" : "Kopfbereich-Logo", + "Upload new header logo" : "Neues Kopfbereich-Logo hochladen", + "Favicon" : "Favicon", + "Upload new favicon" : "Neues Favicon hochladen", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installiere die Imagemagick PHP-Erweiterung mit Unterstützung für SVG-Bilder, um automatisch Favoriten-Icons auf Basis des hochgeladenen Icons und der Farbe zu erstellen.", "You are already using a custom theme" : "Du benutzt bereits ein eigenes Thema", "reset to default" : "Auf Standard zurücksetzen", diff --git a/apps/theming/l10n/de.json b/apps/theming/l10n/de.json index 80f36772bab..385acc7257a 100644 --- a/apps/theming/l10n/de.json +++ b/apps/theming/l10n/de.json @@ -32,6 +32,11 @@ "Login image" : "Anmelde-Bild", "Upload new login background" : "Neuen Anmelde-Hintergrund hochladen", "Remove background image" : "Entferne Hintergrundbild", + "Advanced options" : "Erweiterte Optionen", + "Header logo" : "Kopfbereich-Logo", + "Upload new header logo" : "Neues Kopfbereich-Logo hochladen", + "Favicon" : "Favicon", + "Upload new favicon" : "Neues Favicon hochladen", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installiere die Imagemagick PHP-Erweiterung mit Unterstützung für SVG-Bilder, um automatisch Favoriten-Icons auf Basis des hochgeladenen Icons und der Farbe zu erstellen.", "You are already using a custom theme" : "Du benutzt bereits ein eigenes Thema", "reset to default" : "Auf Standard zurücksetzen", diff --git a/apps/theming/l10n/de_DE.js b/apps/theming/l10n/de_DE.js index 022566c2ee3..027bf5f097f 100644 --- a/apps/theming/l10n/de_DE.js +++ b/apps/theming/l10n/de_DE.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Anmelde-Bild", "Upload new login background" : "Neuen Anmelde-Hintergrund hochladen", "Remove background image" : "Entferne Hintergrundbild", + "Advanced options" : "Erweiterte Optionen", + "Header logo" : "Kopfbereich-Logo", + "Upload new header logo" : "Neues Kopfbereich-Logo hochladen", + "Favicon" : "Favicon", + "Upload new favicon" : "Neues Favicon hochladen", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installieren Sie die Imagemagick PHP-Erweiterung mit Unterstützung für SVG-Bilder, um automatisch Favoriten-Icons auf Basis des hochgeladenen Icons und der Farbe zu erstellen.", "You are already using a custom theme" : "Sie benutzen bereits ein eigenes Thema", "reset to default" : "Auf Standard zurücksetzen", diff --git a/apps/theming/l10n/de_DE.json b/apps/theming/l10n/de_DE.json index 2cb934e738f..b1447a15498 100644 --- a/apps/theming/l10n/de_DE.json +++ b/apps/theming/l10n/de_DE.json @@ -32,6 +32,11 @@ "Login image" : "Anmelde-Bild", "Upload new login background" : "Neuen Anmelde-Hintergrund hochladen", "Remove background image" : "Entferne Hintergrundbild", + "Advanced options" : "Erweiterte Optionen", + "Header logo" : "Kopfbereich-Logo", + "Upload new header logo" : "Neues Kopfbereich-Logo hochladen", + "Favicon" : "Favicon", + "Upload new favicon" : "Neues Favicon hochladen", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installieren Sie die Imagemagick PHP-Erweiterung mit Unterstützung für SVG-Bilder, um automatisch Favoriten-Icons auf Basis des hochgeladenen Icons und der Farbe zu erstellen.", "You are already using a custom theme" : "Sie benutzen bereits ein eigenes Thema", "reset to default" : "Auf Standard zurücksetzen", diff --git a/apps/theming/l10n/es.js b/apps/theming/l10n/es.js index 325cee972ca..5302be90106 100644 --- a/apps/theming/l10n/es.js +++ b/apps/theming/l10n/es.js @@ -6,14 +6,14 @@ OC.L10N.register( "Admin" : "Administración", "a safe home for all your data" : "un hogar seguro para todos tus datos", "Name cannot be empty" : "El nombre no puede estar vacío", - "The given name is too long" : "El nombre provisto es muy largo", - "The given web address is too long" : "La dirección provista es muy larga", - "The given slogan is too long" : "El eslogan provisto es muy largo", + "The given name is too long" : "El nombre provisto es demasiado largo", + "The given web address is too long" : "La dirección provista es demasiado larga", + "The given slogan is too long" : "El eslogan provisto es demasiado largo", "The given color is invalid" : "El color provisto es inválido", "The file was uploaded" : "Se ha subido el archivo", "The uploaded file exceeds the upload_max_filesize directive in php.ini" : "El archivo para subir excede la directiva upload_max_filesize en php.ini", - "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo para subir excede la directiva MAX_FILE_SIZE que se especifió en el formulario HTML", - "The file was only partially uploaded" : "El archivo se ha subido parcialmente", + "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo para subir excede la directiva MAX_FILE_SIZE que se especificó en el formulario HTML", + "The file was only partially uploaded" : "El archivo se ha subido solo parcialmente", "No file was uploaded" : "No se ha subido ningún archivo", "Missing a temporary folder" : "Falta una carpeta temporal", "Could not write file to disk" : "No se puede escribir el archivo en el disco", @@ -31,9 +31,14 @@ OC.L10N.register( "Color" : "Color", "Logo" : "Logo", "Upload new logo" : "Subir nuevo logo", - "Login image" : "Fondo de Pantalla", - "Upload new login background" : "Subir una nueva imagen de fondo", + "Login image" : "Imagen de fondo para inicio de sesión", + "Upload new login background" : "Subir una nueva imagen de fondo para inicio de sesión", "Remove background image" : "Eliminar imagen de fondo", + "Advanced options" : "Opciones avanzadas", + "Header logo" : "Logo de la cabecera", + "Upload new header logo" : "Subir nuevo logo de la cabecera", + "Favicon" : "Favicon", + "Upload new favicon" : "Subir nuevo favicon", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Instala la extensión de PHP Imagemagick con soporte para imágenes SVG para generar automáticamente faviconos basados en el logo y color subidos.", "You are already using a custom theme" : "Ya estás usando un tema personalizado", "reset to default" : "restaurar a configuración inicial", diff --git a/apps/theming/l10n/es.json b/apps/theming/l10n/es.json index e091d8d1b56..4e084f562d8 100644 --- a/apps/theming/l10n/es.json +++ b/apps/theming/l10n/es.json @@ -4,14 +4,14 @@ "Admin" : "Administración", "a safe home for all your data" : "un hogar seguro para todos tus datos", "Name cannot be empty" : "El nombre no puede estar vacío", - "The given name is too long" : "El nombre provisto es muy largo", - "The given web address is too long" : "La dirección provista es muy larga", - "The given slogan is too long" : "El eslogan provisto es muy largo", + "The given name is too long" : "El nombre provisto es demasiado largo", + "The given web address is too long" : "La dirección provista es demasiado larga", + "The given slogan is too long" : "El eslogan provisto es demasiado largo", "The given color is invalid" : "El color provisto es inválido", "The file was uploaded" : "Se ha subido el archivo", "The uploaded file exceeds the upload_max_filesize directive in php.ini" : "El archivo para subir excede la directiva upload_max_filesize en php.ini", - "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo para subir excede la directiva MAX_FILE_SIZE que se especifió en el formulario HTML", - "The file was only partially uploaded" : "El archivo se ha subido parcialmente", + "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo para subir excede la directiva MAX_FILE_SIZE que se especificó en el formulario HTML", + "The file was only partially uploaded" : "El archivo se ha subido solo parcialmente", "No file was uploaded" : "No se ha subido ningún archivo", "Missing a temporary folder" : "Falta una carpeta temporal", "Could not write file to disk" : "No se puede escribir el archivo en el disco", @@ -29,9 +29,14 @@ "Color" : "Color", "Logo" : "Logo", "Upload new logo" : "Subir nuevo logo", - "Login image" : "Fondo de Pantalla", - "Upload new login background" : "Subir una nueva imagen de fondo", + "Login image" : "Imagen de fondo para inicio de sesión", + "Upload new login background" : "Subir una nueva imagen de fondo para inicio de sesión", "Remove background image" : "Eliminar imagen de fondo", + "Advanced options" : "Opciones avanzadas", + "Header logo" : "Logo de la cabecera", + "Upload new header logo" : "Subir nuevo logo de la cabecera", + "Favicon" : "Favicon", + "Upload new favicon" : "Subir nuevo favicon", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Instala la extensión de PHP Imagemagick con soporte para imágenes SVG para generar automáticamente faviconos basados en el logo y color subidos.", "You are already using a custom theme" : "Ya estás usando un tema personalizado", "reset to default" : "restaurar a configuración inicial", diff --git a/apps/theming/l10n/fi.js b/apps/theming/l10n/fi.js index 942b2f781ae..45f5035ca50 100644 --- a/apps/theming/l10n/fi.js +++ b/apps/theming/l10n/fi.js @@ -32,6 +32,11 @@ OC.L10N.register( "Login image" : "Kirjautumissivun kuva", "Upload new login background" : "Lähetä uusi kirjautumissivun taustakuva", "Remove background image" : "Poista taustakuva", + "Advanced options" : "Lisävalinnat", + "Header logo" : "Otsakelogo", + "Upload new header logo" : "Lähetä uusi otsakelogo", + "Favicon" : "Favicon", + "Upload new favicon" : "Lähetä uusi favicon", "You are already using a custom theme" : "Käytät jo kustomoitua ulkoasua", "reset to default" : "palauta oletukseksi", "There is no error, the file uploaded with success" : "Ei virhettä, tiedosto lähetettiin onnistuneesti", diff --git a/apps/theming/l10n/fi.json b/apps/theming/l10n/fi.json index 53fea953b9f..e74c8b008c6 100644 --- a/apps/theming/l10n/fi.json +++ b/apps/theming/l10n/fi.json @@ -30,6 +30,11 @@ "Login image" : "Kirjautumissivun kuva", "Upload new login background" : "Lähetä uusi kirjautumissivun taustakuva", "Remove background image" : "Poista taustakuva", + "Advanced options" : "Lisävalinnat", + "Header logo" : "Otsakelogo", + "Upload new header logo" : "Lähetä uusi otsakelogo", + "Favicon" : "Favicon", + "Upload new favicon" : "Lähetä uusi favicon", "You are already using a custom theme" : "Käytät jo kustomoitua ulkoasua", "reset to default" : "palauta oletukseksi", "There is no error, the file uploaded with success" : "Ei virhettä, tiedosto lähetettiin onnistuneesti", diff --git a/apps/theming/l10n/fr.js b/apps/theming/l10n/fr.js index b59b700d0f2..e920df1becb 100644 --- a/apps/theming/l10n/fr.js +++ b/apps/theming/l10n/fr.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Image de connexion", "Upload new login background" : "Téléverser un nouvel arrière-plan de connexion", "Remove background image" : "Supprimer l'image en arrière-plan", + "Advanced options" : "Options avancées", + "Header logo" : "Logo d'en-tête", + "Upload new header logo" : "Téléverser un nouveau logo d'en-tête", + "Favicon" : "Favicon", + "Upload new favicon" : "Téléverser un nouveau favicon", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installez l'extension PHP Imagemagick avec le support pour les images SVG afin de générer automatiquement les favicons sur base du logo téléversé et de la couleur.", "You are already using a custom theme" : "Vous utilisez déjà un thème personnalisé", "reset to default" : "Restaurer les valeurs par défaut", diff --git a/apps/theming/l10n/fr.json b/apps/theming/l10n/fr.json index 965a3aa47ee..4501667ef8d 100644 --- a/apps/theming/l10n/fr.json +++ b/apps/theming/l10n/fr.json @@ -32,6 +32,11 @@ "Login image" : "Image de connexion", "Upload new login background" : "Téléverser un nouvel arrière-plan de connexion", "Remove background image" : "Supprimer l'image en arrière-plan", + "Advanced options" : "Options avancées", + "Header logo" : "Logo d'en-tête", + "Upload new header logo" : "Téléverser un nouveau logo d'en-tête", + "Favicon" : "Favicon", + "Upload new favicon" : "Téléverser un nouveau favicon", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installez l'extension PHP Imagemagick avec le support pour les images SVG afin de générer automatiquement les favicons sur base du logo téléversé et de la couleur.", "You are already using a custom theme" : "Vous utilisez déjà un thème personnalisé", "reset to default" : "Restaurer les valeurs par défaut", diff --git a/apps/theming/l10n/it.js b/apps/theming/l10n/it.js index b4b593ac690..71ba5745438 100644 --- a/apps/theming/l10n/it.js +++ b/apps/theming/l10n/it.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Immagine di accesso", "Upload new login background" : "Carica nuovo sfondo di accesso", "Remove background image" : "Rimuovi immagine di sfondo", + "Advanced options" : "Opzioni avanzate", + "Header logo" : "Logo dell'intestazione", + "Upload new header logo" : "Carica nuovo logo dell'intestazione", + "Favicon" : "Favicon", + "Upload new favicon" : "Carica nuova favicon", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installa l'estensione Imagemacick di PHP con supporto per le immagini SVG per generare automaticamente favicon basate sul logo caricato e sul colore.", "You are already using a custom theme" : "Stai già usando un tema personalizzato", "reset to default" : "ripristina valori predefiniti", diff --git a/apps/theming/l10n/it.json b/apps/theming/l10n/it.json index e430f2791f5..a657c561d78 100644 --- a/apps/theming/l10n/it.json +++ b/apps/theming/l10n/it.json @@ -32,6 +32,11 @@ "Login image" : "Immagine di accesso", "Upload new login background" : "Carica nuovo sfondo di accesso", "Remove background image" : "Rimuovi immagine di sfondo", + "Advanced options" : "Opzioni avanzate", + "Header logo" : "Logo dell'intestazione", + "Upload new header logo" : "Carica nuovo logo dell'intestazione", + "Favicon" : "Favicon", + "Upload new favicon" : "Carica nuova favicon", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Installa l'estensione Imagemacick di PHP con supporto per le immagini SVG per generare automaticamente favicon basate sul logo caricato e sul colore.", "You are already using a custom theme" : "Stai già usando un tema personalizzato", "reset to default" : "ripristina valori predefiniti", diff --git a/apps/theming/l10n/pt_BR.js b/apps/theming/l10n/pt_BR.js index 0cebf02c69b..a04d0f22d30 100644 --- a/apps/theming/l10n/pt_BR.js +++ b/apps/theming/l10n/pt_BR.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Imagem de login", "Upload new login background" : "Enviar nova imagem de fundo para o login", "Remove background image" : "Excluir a imagem de fundo", + "Advanced options" : "Opções avançadas", + "Header logo" : "Logotipo de cabeçalho", + "Upload new header logo" : "Enviar novo logotipo de cabeçalho", + "Favicon" : "Ícone de favoritos", + "Upload new favicon" : "Enviar novo ícone de favorito", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Instale a extensão PHP Imagemagick com suporte a imagens SVG para gerar favicons automaticamente, com base no logotipo e na cor enviados.", "You are already using a custom theme" : "Você já está usando um tema personalizado", "reset to default" : "restaurar ao padrão", diff --git a/apps/theming/l10n/pt_BR.json b/apps/theming/l10n/pt_BR.json index 7fd9150fd09..0c58de03148 100644 --- a/apps/theming/l10n/pt_BR.json +++ b/apps/theming/l10n/pt_BR.json @@ -32,6 +32,11 @@ "Login image" : "Imagem de login", "Upload new login background" : "Enviar nova imagem de fundo para o login", "Remove background image" : "Excluir a imagem de fundo", + "Advanced options" : "Opções avançadas", + "Header logo" : "Logotipo de cabeçalho", + "Upload new header logo" : "Enviar novo logotipo de cabeçalho", + "Favicon" : "Ícone de favoritos", + "Upload new favicon" : "Enviar novo ícone de favorito", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Instale a extensão PHP Imagemagick com suporte a imagens SVG para gerar favicons automaticamente, com base no logotipo e na cor enviados.", "You are already using a custom theme" : "Você já está usando um tema personalizado", "reset to default" : "restaurar ao padrão", diff --git a/apps/theming/l10n/ru.js b/apps/theming/l10n/ru.js index 058f36cbfb6..945ab1c7d6d 100644 --- a/apps/theming/l10n/ru.js +++ b/apps/theming/l10n/ru.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Изображение экрана входа в систему", "Upload new login background" : "Загрузить новый фон для экрана входа в систему", "Remove background image" : "Убрать фоновое изображение ", + "Advanced options" : "Дополнительные параметры", + "Header logo" : "Логотип заголовка", + "Upload new header logo" : "Загрузить логотип заголовка", + "Favicon" : "Favicon (значок сайта)", + "Upload new favicon" : "Загрузить значок сайта", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Для автоматической генерации favicon на основе загруженного логотипа и цвета нужно установить PHP расширение Imagemagick с поддержкой изображений SVG ", "You are already using a custom theme" : "Вы уже используете настраиваемую тему", "reset to default" : "сброс до настроек по-умолчанию", diff --git a/apps/theming/l10n/ru.json b/apps/theming/l10n/ru.json index 8aaee6c18af..871416e3c79 100644 --- a/apps/theming/l10n/ru.json +++ b/apps/theming/l10n/ru.json @@ -32,6 +32,11 @@ "Login image" : "Изображение экрана входа в систему", "Upload new login background" : "Загрузить новый фон для экрана входа в систему", "Remove background image" : "Убрать фоновое изображение ", + "Advanced options" : "Дополнительные параметры", + "Header logo" : "Логотип заголовка", + "Upload new header logo" : "Загрузить логотип заголовка", + "Favicon" : "Favicon (значок сайта)", + "Upload new favicon" : "Загрузить значок сайта", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Для автоматической генерации favicon на основе загруженного логотипа и цвета нужно установить PHP расширение Imagemagick с поддержкой изображений SVG ", "You are already using a custom theme" : "Вы уже используете настраиваемую тему", "reset to default" : "сброс до настроек по-умолчанию", diff --git a/apps/theming/l10n/tr.js b/apps/theming/l10n/tr.js index 287678c3765..f8955ce9300 100644 --- a/apps/theming/l10n/tr.js +++ b/apps/theming/l10n/tr.js @@ -34,6 +34,11 @@ OC.L10N.register( "Login image" : "Oturum açma görseli", "Upload new login background" : "Yeni oturum açma art alanı yükle", "Remove background image" : "Art alan görselini kaldır", + "Advanced options" : "Gelişmiş ayarlar", + "Header logo" : "Üst bilgi logosu", + "Upload new header logo" : "Yeni üst bilgi logosu yükle", + "Favicon" : "Favicon", + "Upload new favicon" : "Yeni favicon yükle", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Yüklenen logo ve renge göre otomatik olarak favicon üretilmesi için Imagemagick PHP eklentisini SVG desteği ile kurun.", "You are already using a custom theme" : "Zaten özel bir tema kullanıyorsunuz", "reset to default" : "varsayılana dön", diff --git a/apps/theming/l10n/tr.json b/apps/theming/l10n/tr.json index d4c587eb181..86b5742690a 100644 --- a/apps/theming/l10n/tr.json +++ b/apps/theming/l10n/tr.json @@ -32,6 +32,11 @@ "Login image" : "Oturum açma görseli", "Upload new login background" : "Yeni oturum açma art alanı yükle", "Remove background image" : "Art alan görselini kaldır", + "Advanced options" : "Gelişmiş ayarlar", + "Header logo" : "Üst bilgi logosu", + "Upload new header logo" : "Yeni üst bilgi logosu yükle", + "Favicon" : "Favicon", + "Upload new favicon" : "Yeni favicon yükle", "Install the Imagemagick PHP extension with support for SVG images to automatically generate favicons based on the uploaded logo and color." : "Yüklenen logo ve renge göre otomatik olarak favicon üretilmesi için Imagemagick PHP eklentisini SVG desteği ile kurun.", "You are already using a custom theme" : "Zaten özel bir tema kullanıyorsunuz", "reset to default" : "varsayılana dön", diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index cb117c72a2b..ea9925f3a64 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -111,7 +111,7 @@ style('theming', 'settings-admin'); <input type="hidden" name="key" value="favicon" /> <label for="upload-login-favicon"><span><?php p($l->t('Favicon')) ?></span></label> <input id="upload-login-favicon" class="fileupload" name="image" type="file"> - <label for="upload-login-favicon" class="button icon-upload svg" id="upload-login-favicon" title="<?php p($l->t("Upload new favion")) ?>"></label> + <label for="upload-login-favicon" class="button icon-upload svg" id="upload-login-favicon" title="<?php p($l->t("Upload new favicon")) ?>"></label> <div class="image-preview"></div> <div data-setting="faviconMime" data-toggle="tooltip" data-original-title="<?php p($l->t('Reset to default')); ?>" class="theme-undo icon icon-history"></div> </form> diff --git a/apps/twofactor_backupcodes/l10n/pl.js b/apps/twofactor_backupcodes/l10n/pl.js index c37c31d1246..93174e402d8 100644 --- a/apps/twofactor_backupcodes/l10n/pl.js +++ b/apps/twofactor_backupcodes/l10n/pl.js @@ -13,6 +13,7 @@ OC.L10N.register( "You created two-factor backup codes for your account" : "Stworzyłeś zapasowe kody uwierzytelnienia dwuetapowego swojego konta", "Backup code" : "Kod zapasowy", "Use backup code" : "Użyj kodu zapasowego", + "Two factor backup codes" : "Kody zapasowe uwierzytelnienia dwuskładnikowego", "Second-factor backup codes" : "Kody zapasowe uwierzytelnienia dwuskładnikowego" }, "nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"); diff --git a/apps/twofactor_backupcodes/l10n/pl.json b/apps/twofactor_backupcodes/l10n/pl.json index d427dcd9060..5067c191e03 100644 --- a/apps/twofactor_backupcodes/l10n/pl.json +++ b/apps/twofactor_backupcodes/l10n/pl.json @@ -11,6 +11,7 @@ "You created two-factor backup codes for your account" : "Stworzyłeś zapasowe kody uwierzytelnienia dwuetapowego swojego konta", "Backup code" : "Kod zapasowy", "Use backup code" : "Użyj kodu zapasowego", + "Two factor backup codes" : "Kody zapasowe uwierzytelnienia dwuskładnikowego", "Second-factor backup codes" : "Kody zapasowe uwierzytelnienia dwuskładnikowego" },"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);" }
\ No newline at end of file diff --git a/apps/updatenotification/l10n/tr.js b/apps/updatenotification/l10n/tr.js index 508ed1eccfd..78dbb84bd9c 100644 --- a/apps/updatenotification/l10n/tr.js +++ b/apps/updatenotification/l10n/tr.js @@ -32,6 +32,7 @@ OC.L10N.register( "Update for {app} to version %s is available." : "{app} uygulaması için %s sürümü güncellemesi yayınlanmış.", "Update notification" : "Güncelleme bildirimi", "A new version is available: %s" : "Yeni bir sürüm yayınlanmış: %s", + "The version you are running is not maintained anymore. Please make sure to update to a supported version as soon as possible." : "Kullanmakta olduğunuz sürüm artık desteklenmiyor. Lütfen en kısa sürede desteklenen bir sürüme güncellemeyi ihmal etmeyin.", "Download now" : "İndir", "Checked on %s" : "Son denetim: %s", "The selected update channel makes dedicated notifications for the server obsolete." : "Seçilmiş güncelleme kanalı kullanımdan kalkmış sunucu bildirimleri için kullanılıyor.", diff --git a/apps/updatenotification/l10n/tr.json b/apps/updatenotification/l10n/tr.json index 96882619b59..abd8b8d9b90 100644 --- a/apps/updatenotification/l10n/tr.json +++ b/apps/updatenotification/l10n/tr.json @@ -30,6 +30,7 @@ "Update for {app} to version %s is available." : "{app} uygulaması için %s sürümü güncellemesi yayınlanmış.", "Update notification" : "Güncelleme bildirimi", "A new version is available: %s" : "Yeni bir sürüm yayınlanmış: %s", + "The version you are running is not maintained anymore. Please make sure to update to a supported version as soon as possible." : "Kullanmakta olduğunuz sürüm artık desteklenmiyor. Lütfen en kısa sürede desteklenen bir sürüme güncellemeyi ihmal etmeyin.", "Download now" : "İndir", "Checked on %s" : "Son denetim: %s", "The selected update channel makes dedicated notifications for the server obsolete." : "Seçilmiş güncelleme kanalı kullanımdan kalkmış sunucu bildirimleri için kullanılıyor.", diff --git a/apps/user_ldap/l10n/pt_BR.js b/apps/user_ldap/l10n/pt_BR.js index d8025e6ba20..aa5ae1ce61e 100644 --- a/apps/user_ldap/l10n/pt_BR.js +++ b/apps/user_ldap/l10n/pt_BR.js @@ -80,7 +80,7 @@ OC.L10N.register( "When logging in, %s will find the user based on the following attributes:" : "Ao entrar, %s vai encontrar o usuário com base nos seguintes atributos:", "LDAP / AD Username:" : "Nome do usuário LDAP / AD:", "Allows login against the LDAP / AD username, which is either \"uid\" or \"sAMAccountName\" and will be detected." : "Permite login com o nome de usuário LDAP / AD, o qual é \"uid\" ou \"sAMAccountName\" e será detectado.", - "LDAP / AD Email Address:" : "Endereço de e-mail LDAP / AD:", + "LDAP / AD Email Address:" : "Endereço de email LDAP / AD:", "Allows login against an email attribute. \"mail\" and \"mailPrimaryAddress\" allowed." : "Permite login com um atributo de email. \"Mail\" e \"mailPrimaryAddress\" são permitidos.", "Other Attributes:" : "Outros Atributos:", "Defines the filter to apply, when login is attempted. \"%%uid\" replaces the username in the login action. Example: \"uid=%%uid\"" : "Define o filtro a aplicar quando o login é tentado. \"%%uid\" substitui o nome de usuário durante o login. Por exemplo: \"uid=%%uid\"", @@ -172,8 +172,8 @@ OC.L10N.register( "Leave empty for user's default quota. Otherwise, specify an LDAP/AD attribute." : "Deixe vazio para a cota padrão do usuário. Caso contrário, especifique um atributo LDAP/AD", "Quota Default" : "Cota Padrão", "Override default quota for LDAP users who do not have a quota set in the Quota Field." : "Substituir a cota padrão para usuários LDAP que não têm um conjunto de cotas no Campo Cota.", - "Email Field" : "Campo de e-mail", - "Set the user's email from their LDAP attribute. Leave it empty for default behaviour." : "Defina o e-mail do usuário de seu atributo LDAP. Deixe vazio para o comportamento padrão.", + "Email Field" : "Campo de email", + "Set the user's email from their LDAP attribute. Leave it empty for default behaviour." : "Defina o email do usuário de seu atributo LDAP. Deixe vazio para o comportamento padrão.", "User Home Folder Naming Rule" : "Regra de nomeação de pasta de usuário Home", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." : "Deixe vazio para nome de usuário (padrão). Caso contrário, especifique um atributo LDAP/AD.", "Internal Username" : "Nome de usuário interno", diff --git a/apps/user_ldap/l10n/pt_BR.json b/apps/user_ldap/l10n/pt_BR.json index 2d74bae7700..0fb333dada5 100644 --- a/apps/user_ldap/l10n/pt_BR.json +++ b/apps/user_ldap/l10n/pt_BR.json @@ -78,7 +78,7 @@ "When logging in, %s will find the user based on the following attributes:" : "Ao entrar, %s vai encontrar o usuário com base nos seguintes atributos:", "LDAP / AD Username:" : "Nome do usuário LDAP / AD:", "Allows login against the LDAP / AD username, which is either \"uid\" or \"sAMAccountName\" and will be detected." : "Permite login com o nome de usuário LDAP / AD, o qual é \"uid\" ou \"sAMAccountName\" e será detectado.", - "LDAP / AD Email Address:" : "Endereço de e-mail LDAP / AD:", + "LDAP / AD Email Address:" : "Endereço de email LDAP / AD:", "Allows login against an email attribute. \"mail\" and \"mailPrimaryAddress\" allowed." : "Permite login com um atributo de email. \"Mail\" e \"mailPrimaryAddress\" são permitidos.", "Other Attributes:" : "Outros Atributos:", "Defines the filter to apply, when login is attempted. \"%%uid\" replaces the username in the login action. Example: \"uid=%%uid\"" : "Define o filtro a aplicar quando o login é tentado. \"%%uid\" substitui o nome de usuário durante o login. Por exemplo: \"uid=%%uid\"", @@ -170,8 +170,8 @@ "Leave empty for user's default quota. Otherwise, specify an LDAP/AD attribute." : "Deixe vazio para a cota padrão do usuário. Caso contrário, especifique um atributo LDAP/AD", "Quota Default" : "Cota Padrão", "Override default quota for LDAP users who do not have a quota set in the Quota Field." : "Substituir a cota padrão para usuários LDAP que não têm um conjunto de cotas no Campo Cota.", - "Email Field" : "Campo de e-mail", - "Set the user's email from their LDAP attribute. Leave it empty for default behaviour." : "Defina o e-mail do usuário de seu atributo LDAP. Deixe vazio para o comportamento padrão.", + "Email Field" : "Campo de email", + "Set the user's email from their LDAP attribute. Leave it empty for default behaviour." : "Defina o email do usuário de seu atributo LDAP. Deixe vazio para o comportamento padrão.", "User Home Folder Naming Rule" : "Regra de nomeação de pasta de usuário Home", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." : "Deixe vazio para nome de usuário (padrão). Caso contrário, especifique um atributo LDAP/AD.", "Internal Username" : "Nome de usuário interno", diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php index a5bbc957ac9..e6a01a17d25 100644 --- a/apps/user_ldap/lib/Connection.php +++ b/apps/user_ldap/lib/Connection.php @@ -126,6 +126,9 @@ class Connection extends LDAPUtility { public function __clone() { $this->configuration = new Configuration($this->configPrefix, !is_null($this->configID)); + if(count($this->bindResult) !== 0 && $this->bindResult['result'] === true) { + $this->bindResult = []; + } $this->ldapConnectionRes = null; $this->dontDestruct = true; } diff --git a/apps/workflowengine/l10n/de.js b/apps/workflowengine/l10n/de.js index 33558774c84..62e881e4ef4 100644 --- a/apps/workflowengine/l10n/de.js +++ b/apps/workflowengine/l10n/de.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Saved" : "Gespeichert", "Saving failed:" : "Speichern fehlgeschlagen:", diff --git a/apps/workflowengine/l10n/de.json b/apps/workflowengine/l10n/de.json index 5d777ff9101..02ff5ca677c 100644 --- a/apps/workflowengine/l10n/de.json +++ b/apps/workflowengine/l10n/de.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Saved" : "Gespeichert", "Saving failed:" : "Speichern fehlgeschlagen:", diff --git a/apps/workflowengine/l10n/de_DE.js b/apps/workflowengine/l10n/de_DE.js index a8349e499a8..3389b9f3ccd 100644 --- a/apps/workflowengine/l10n/de_DE.js +++ b/apps/workflowengine/l10n/de_DE.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Saved" : "Gespeichert", "Saving failed:" : "Speichern fehlgeschlagen:", diff --git a/apps/workflowengine/l10n/de_DE.json b/apps/workflowengine/l10n/de_DE.json index 7e01b378c93..c04cec6f458 100644 --- a/apps/workflowengine/l10n/de_DE.json +++ b/apps/workflowengine/l10n/de_DE.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Saved" : "Gespeichert", "Saving failed:" : "Speichern fehlgeschlagen:", diff --git a/apps/workflowengine/l10n/es.js b/apps/workflowengine/l10n/es.js index e628e101fd5..3ea757d7313 100644 --- a/apps/workflowengine/l10n/es.js +++ b/apps/workflowengine/l10n/es.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "La lista de grupos está vacía", "Unable to retrieve the group list" : "No es posible recibir la lista de grupos", "Saved" : "Guardado", "Saving failed:" : "Fallo al guardar:", diff --git a/apps/workflowengine/l10n/es.json b/apps/workflowengine/l10n/es.json index 6620c4a765e..11e14dc1371 100644 --- a/apps/workflowengine/l10n/es.json +++ b/apps/workflowengine/l10n/es.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "La lista de grupos está vacía", "Unable to retrieve the group list" : "No es posible recibir la lista de grupos", "Saved" : "Guardado", "Saving failed:" : "Fallo al guardar:", diff --git a/apps/workflowengine/l10n/fr.js b/apps/workflowengine/l10n/fr.js index 5d66c6dafd5..2e3af87bb7e 100644 --- a/apps/workflowengine/l10n/fr.js +++ b/apps/workflowengine/l10n/fr.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "La liste du groupe est vide", "Unable to retrieve the group list" : "Impossible de récupérer la liste du groupe", "Saved" : "Sauvegardé", "Saving failed:" : "L'enregistrement a échoué:", diff --git a/apps/workflowengine/l10n/fr.json b/apps/workflowengine/l10n/fr.json index e85bec67c94..bc8cad7661f 100644 --- a/apps/workflowengine/l10n/fr.json +++ b/apps/workflowengine/l10n/fr.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "La liste du groupe est vide", "Unable to retrieve the group list" : "Impossible de récupérer la liste du groupe", "Saved" : "Sauvegardé", "Saving failed:" : "L'enregistrement a échoué:", diff --git a/apps/workflowengine/l10n/it.js b/apps/workflowengine/l10n/it.js index a16fec791f0..7a620f7e44f 100644 --- a/apps/workflowengine/l10n/it.js +++ b/apps/workflowengine/l10n/it.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "L'elenco dei gruppi è vuoto", "Unable to retrieve the group list" : "Impossibile recuperare l'elenco dei gruppi", "Saved" : "Salvato", "Saving failed:" : "Salvataggio non riuscito:", diff --git a/apps/workflowengine/l10n/it.json b/apps/workflowengine/l10n/it.json index 7ced857a54c..7ab3c9ce9c5 100644 --- a/apps/workflowengine/l10n/it.json +++ b/apps/workflowengine/l10n/it.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "L'elenco dei gruppi è vuoto", "Unable to retrieve the group list" : "Impossibile recuperare l'elenco dei gruppi", "Saved" : "Salvato", "Saving failed:" : "Salvataggio non riuscito:", diff --git a/apps/workflowengine/l10n/pt_BR.js b/apps/workflowengine/l10n/pt_BR.js index e6f5b05ed8c..b7e50112f40 100644 --- a/apps/workflowengine/l10n/pt_BR.js +++ b/apps/workflowengine/l10n/pt_BR.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "Lista de grupos vazia", "Unable to retrieve the group list" : "Impossível recuperar a lista do grupo", "Saved" : "Salvo", "Saving failed:" : "A gravação falhou:", diff --git a/apps/workflowengine/l10n/pt_BR.json b/apps/workflowengine/l10n/pt_BR.json index 3a5dd45540c..9d476397ed3 100644 --- a/apps/workflowengine/l10n/pt_BR.json +++ b/apps/workflowengine/l10n/pt_BR.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "Lista de grupos vazia", "Unable to retrieve the group list" : "Impossível recuperar a lista do grupo", "Saved" : "Salvo", "Saving failed:" : "A gravação falhou:", diff --git a/apps/workflowengine/l10n/ru.js b/apps/workflowengine/l10n/ru.js index 9c5010ff0f0..e7b035b7402 100644 --- a/apps/workflowengine/l10n/ru.js +++ b/apps/workflowengine/l10n/ru.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "Список групп пуст", "Unable to retrieve the group list" : "Не удается получить список групп", "Saved" : "Сохранено", "Saving failed:" : "Ошибка при сохранении:", diff --git a/apps/workflowengine/l10n/ru.json b/apps/workflowengine/l10n/ru.json index 6764fda9843..d3c5dff332e 100644 --- a/apps/workflowengine/l10n/ru.json +++ b/apps/workflowengine/l10n/ru.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "Список групп пуст", "Unable to retrieve the group list" : "Не удается получить список групп", "Saved" : "Сохранено", "Saving failed:" : "Ошибка при сохранении:", diff --git a/apps/workflowengine/l10n/tr.js b/apps/workflowengine/l10n/tr.js index e41710f175f..d4b2ccfa1dc 100644 --- a/apps/workflowengine/l10n/tr.js +++ b/apps/workflowengine/l10n/tr.js @@ -1,6 +1,7 @@ OC.L10N.register( "workflowengine", { + "Group list is empty" : "Grup listesi boş", "Unable to retrieve the group list" : "Grup listesi alınamadı", "Saved" : "Kaydedildi", "Saving failed:" : "Kaydedilemedi:", diff --git a/apps/workflowengine/l10n/tr.json b/apps/workflowengine/l10n/tr.json index 40f33f4cf13..e47333e5fa2 100644 --- a/apps/workflowengine/l10n/tr.json +++ b/apps/workflowengine/l10n/tr.json @@ -1,4 +1,5 @@ { "translations": { + "Group list is empty" : "Grup listesi boş", "Unable to retrieve the group list" : "Grup listesi alınamadı", "Saved" : "Kaydedildi", "Saving failed:" : "Kaydedilemedi:", diff --git a/build/.phan/config.php b/build/.phan/config.php index 1bdaddc0e05..9bd61ee5687 100644 --- a/build/.phan/config.php +++ b/build/.phan/config.php @@ -16,17 +16,24 @@ return [ // Thus, both first-party and third-party code being used by // your application should be included in this list. 'directory_list' => [ - 'build/.phan/stubs', '3rdparty', - 'lib/composer', - 'themes', - 'lib/', 'apps/', + 'build/.phan/stubs', 'core/', - 'ocs/', + 'lib/', + 'lib/composer', 'ocs-provider/', + 'ocs/', 'settings/', 'tests/lib/Util/User', + 'themes', + ], + 'file_list' => [ + 'index.php', + 'public.php', + 'remote.php', + 'status.php', + 'version.php', ], // A directory list that defines files that will be excluded @@ -40,9 +47,8 @@ return [ // party code, directories containing that code // should be added to the `directory_list` as // to `exclude_analysis_directory_list`. - "exclude_analysis_directory_list" => [ + 'exclude_analysis_directory_list' => [ '3rdparty', - 'lib/composer', 'apps/admin_audit/composer', 'apps/admin_audit/tests', 'apps/comments/composer', @@ -88,8 +94,38 @@ return [ 'apps/user_ldap/tests', 'apps/workflowengine/composer', 'apps/workflowengine/tests', + 'build/.phan/', + 'lib/composer', ], + // A file list that defines files that will be excluded + // from parsing and analysis and will not be read at all. + // + // This is useful for excluding hopelessly unanalyzable + // files that can't be removed for whatever reason. + 'exclude_file_list' => [ + 'apps/encryption/appinfo/routes.php', + 'apps/federation/appinfo/routes.php', + 'apps/files/appinfo/routes.php', + 'apps/files_external/appinfo/routes.php', + 'apps/files_trashbin/appinfo/routes.php', + 'apps/files_versions/appinfo/routes.php', + 'apps/testing/appinfo/routes.php', + 'apps/user_ldap/appinfo/routes.php', + 'settings/routes.php', + 'settings/ajax/updateapp.php', + 'settings/ajax/uninstallapp.php', + 'settings/ajax/togglesubadmins.php', + 'settings/ajax/setquota.php', + 'settings/ajax/enableapp.php', + 'settings/ajax/disableapp.php', + 'core/register_command.php', + 'ocs/routes.php', + 'ocs/v1.php', + 'core/routes.php', + ], + + // The number of processes to fork off during the analysis // phase. 'processes' => 10, diff --git a/core/js/files/client.js b/core/js/files/client.js index 0109ab9fdbf..e16facbde07 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -49,7 +49,8 @@ xmlNamespaces: { 'DAV:': 'd', 'http://owncloud.org/ns': 'oc', - 'http://nextcloud.org/ns': 'nc' + 'http://nextcloud.org/ns': 'nc', + 'http://open-collaboration-services.org/ns': 'ocs' } }; if (options.userName) { @@ -65,6 +66,7 @@ Client.NS_OWNCLOUD = 'http://owncloud.org/ns'; Client.NS_NEXTCLOUD = 'http://nextcloud.org/ns'; Client.NS_DAV = 'DAV:'; + Client.NS_OCS = 'http://open-collaboration-services.org/ns'; Client.PROPERTY_GETLASTMODIFIED = '{' + Client.NS_DAV + '}getlastmodified'; Client.PROPERTY_GETETAG = '{' + Client.NS_DAV + '}getetag'; @@ -75,6 +77,7 @@ Client.PROPERTY_SIZE = '{' + Client.NS_OWNCLOUD + '}size'; Client.PROPERTY_GETCONTENTLENGTH = '{' + Client.NS_DAV + '}getcontentlength'; Client.PROPERTY_ISENCRYPTED = '{' + Client.NS_DAV + '}is-encrypted'; + Client.PROPERTY_SHARE_PERMISSIONS = '{' + Client.NS_OCS + '}share-permissions'; Client.PROTOCOL_HTTP = 'http'; Client.PROTOCOL_HTTPS = 'https'; @@ -125,6 +128,10 @@ * Encryption state */ [Client.NS_NEXTCLOUD, 'is-encrypted'], + /** + * Share permissions + */ + [Client.NS_OCS, 'share-permissions'] ]; /** @@ -373,6 +380,11 @@ } } + var sharePermissionsProp = props[Client.PROPERTY_SHARE_PERMISSIONS]; + if (!_.isUndefined(sharePermissionsProp)) { + data.sharePermissions = parseInt(sharePermissionsProp); + } + var mounTypeProp = props['{' + Client.NS_NEXTCLOUD + '}mount-type']; if (!_.isUndefined(mounTypeProp)) { data.mountType = mounTypeProp; diff --git a/core/js/files/fileinfo.js b/core/js/files/fileinfo.js index 1fc239da47a..b4ac016f90c 100644 --- a/core/js/files/fileinfo.js +++ b/core/js/files/fileinfo.js @@ -132,7 +132,12 @@ /** * @type boolean */ - hasPreview: true + hasPreview: true, + + /** + * @type int + */ + sharePermissions: null }; if (!OC.Files) { diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index acb32fd3892..c845e607fc5 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -18,14 +18,14 @@ OC.L10N.register( "Password reset is disabled" : "A redefinição de senha está desabilitada", "Couldn't reset password because the token is invalid" : "Não foi possível redefinir a senha porque o token é inválido", "Couldn't reset password because the token is expired" : "Não foi possível redefinir a senha porque o token expirou", - "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Não foi possível enviar e-mail de redefinição porque não há nenhum endereço de e-mail para este nome de usuário. Entre em contato com o administrador.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Não foi possível enviar email de redefinição porque não há nenhum endereço de email para este nome de usuário. Entre em contato com o administrador.", "%s password reset" : "%s redefinir senha", "Password reset" : "Redefinir a senha", - "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no botão abaixo para redefinir sua senha. Se você não solicitou isso, ignore este e-mail.", - "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no link abaixo para redefinir sua senha. Se você não solicitou isso, ignore este e-mail.", + "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no botão abaixo para redefinir sua senha. Se você não solicitou isso, ignore este email.", + "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no link abaixo para redefinir sua senha. Se você não solicitou isso, ignore este email.", "Reset your password" : "Redefinir sua senha", - "Couldn't send reset email. Please contact your administrator." : "Não foi possível enviar o e-mail de redefinição. Por favor, contate o administrador.", - "Couldn't send reset email. Please make sure your username is correct." : "Não foi possível enviar o e-mail de redefinição. Verifique se o seu nome de usuário está correto.", + "Couldn't send reset email. Please contact your administrator." : "Não foi possível enviar o email de redefinição. Por favor, contate o administrador.", + "Couldn't send reset email. Please make sure your username is correct." : "Não foi possível enviar o email de redefinição. Verifique se o seu nome de usuário está correto.", "Preparing update" : "Preparando a atualização", "[%d / %d]: %s" : "[%d / %d]: %s", "Repair warning: " : "Aviso da reparação:", @@ -75,7 +75,7 @@ OC.L10N.register( "Failed to authenticate, try again" : "Falha na autenticação, tente novamente", "seconds ago" : "segundos atrás", "Logging in …" : "Entrando...", - "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator." : "O link para redefinir sua senha foi enviado para seu e-mail. Se você não recebê-lo dentro de um período razoável de tempo, verifique suas pastas de spam/lixo.<br> Se ele não estiver lá, pergunte ao administrador local.", + "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator." : "O link para redefinir sua senha foi enviado para seu email. Se você não recebê-lo dentro de um período razoável de tempo, verifique suas pastas de spam/lixo.<br> Se ele não estiver lá, pergunte ao administrador local.", "Your files are encrypted. There will be no way to get your data back after your password is reset.<br />If you are not sure what to do, please contact your administrator before you continue. <br />Do you really want to continue?" : "Seus arquivos são criptografados. Não existe nenhuma maneira de ter seus dados de volta depois que sua senha seja redefinida.<br /> Se você não tem certeza do que fazer, por favor contate seu administrador antes de continuar.<br />Você realmente deseja continuar?", "I know what I'm doing" : "Eu sei o que estou fazendo", "Password can not be changed. Please contact your administrator." : "A senha não pôde ser alterada. Por favor, contate o administrador.", @@ -111,7 +111,7 @@ OC.L10N.register( "Strong password" : "Senha forte", "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Seu servidor web ainda não está configurado corretamente para permitir a sincronização de arquivos, porque a interface do WebDAV parece estar quebrada.", "Your web server is not properly set up to resolve \"{url}\". Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "Seu servidor web não está configurado corretamente para resolver \"{url}\". Mais informações podem ser encontradas na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentação</a>.", - "This server has no working Internet connection: Multiple endpoints could not be reached. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. Establish a connection from this server to the Internet to enjoy all features." : "Este servidor não possui conexão com a internet: Vários pontos não puderam ser acessados. Isso significa que alguns dos recursos como montagem de armazenamento externo, notificações sobre atualizações ou instalação de aplicativos de terceiros não funcionarão. Acesso a arquivos remotos e envio de e-mails de notificação não funcionarão também. Estabeleça uma conexão deste servidor com a Internet para aproveitar todos os recursos.", + "This server has no working Internet connection: Multiple endpoints could not be reached. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. Establish a connection from this server to the Internet to enjoy all features." : "Este servidor não possui conexão com a internet: Vários pontos não puderam ser acessados. Isso significa que alguns dos recursos como montagem de armazenamento externo, notificações sobre atualizações ou instalação de aplicativos de terceiros não funcionarão. Acesso a arquivos remotos e envio de emails de notificação não funcionarão também. Estabeleça uma conexão deste servidor com a Internet para aproveitar todos os recursos.", "No memory cache has been configured. To enhance performance, please configure a memcache, if available. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "Nenhum cache de memória foi configurado. Para melhorar o desempenho, configure um memcache, se disponível. Mais informações podem ser encontradas na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentação</a>.", "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "/dev/urandom não é legível pelo PHP, o que é altamente desencorajado por razões de segurança. Mais informações podem ser encontradas na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentação</a>.", "You are currently running PHP {version}. Upgrade your PHP version to take advantage of <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{phpLink}\">performance and security updates provided by the PHP Group</a> as soon as your distribution supports it." : "Você está executando o PHP {versão}. Atualize esta versão para aproveitar as <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{phpLink}\">atualizações de desempenho e segurança fornecidas pelo Grupo PHP</a> assim que sua distribuição a suportar.", @@ -148,18 +148,18 @@ OC.L10N.register( "Link" : "Link", "Password protect" : "Proteger com senha", "Allow editing" : "Permitir edição", - "Email link to person" : "Enviar link por e-mail", + "Email link to person" : "Enviar link por email", "Send" : "Enviar", "Allow upload and editing" : "Permitir envio e edição", "Read only" : "Somente leitura", "File drop (upload only)" : "Zona de arquivos (somente envio)", "Shared with you and the group {group} by {owner}" : "Compartilhado com você e com o grupo {group} por {owner}", "Shared with you by {owner}" : "Compartilhado com você por {owner}", - "Choose a password for the mail share" : "Escolha uma senha para o compartilhamento de e-mail", + "Choose a password for the mail share" : "Escolha uma senha para o compartilhamento de email", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatiorDisplayName}} compartilhou via link", "group" : "grupo", "remote" : "remoto", - "email" : "e-mail", + "email" : "email", "shared by {sharer}" : "compartilhado por {sharer}", "Unshare" : "Descompartilhar", "Can reshare" : "Pode compartilhar novamente", @@ -182,9 +182,9 @@ OC.L10N.register( "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartilhar", - "Name or email address..." : "Nome ou endereço de e-mail...", + "Name or email address..." : "Nome ou endereço de email...", "Name or federated cloud ID..." : "Nome ou ID de cloud federada...", - "Name, federated cloud ID or email address..." : "Nome, ID de cloud federada ou e-mail...", + "Name, federated cloud ID or email address..." : "Nome, ID de cloud federada ou email...", "Name..." : "Nome...", "Error" : "Erro", "Error removing share" : "Erro na exclusão do compartilhamento", @@ -275,7 +275,7 @@ OC.L10N.register( "Please contact your administrator." : "Por favor, contacte o administrador.", "An internal error occurred." : "Ocorreu um erro interno.", "Please try again or contact your administrator." : "Por favor tente novamente ou contacte o administrador.", - "Username or email" : "Nome de usuário ou e-mail", + "Username or email" : "Nome de usuário ou email", "Log in" : "Entrar", "Wrong password." : "Senha errada", "We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds." : "Detectamos várias tentativas de login inválidas de seu IP. Portanto, seu próximo login será desacelerado em até 30 segundos.", @@ -335,9 +335,9 @@ OC.L10N.register( "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\" rel=\"noreferrer\">security tips</a>." : "O cabeçalho HTTP \"Strict-Transport-Security\" não está configurado para ao menos \"{seconds}\" segundos. Para uma segurança aprimorada, recomendamos habilitar HSTS como descrito em nossas <a href=\"{docUrl}\" rel=\"noreferrer\">dicas de segurança</a>.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our <a href=\"{docUrl}\">security tips</a>." : "Você está acessando este site via HTTP. Recomendamos que configure seu servidor para exigir o uso de HTTPS, conforme descrito em nossas <a href=\"{docUrl}\">dicas de segurança</a>.", "Shared with {recipients}" : "Compartilhado com {recipients}", - "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo, ID de cloud federada ou um e-mail.", + "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo, ID de cloud federada ou um email.", "Share with other people by entering a user or group or a federated cloud ID." : "Compartilhe com outras pessoas entrando um usuário, grupo ou ID de nuvem federada.", - "Share with other people by entering a user or group or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo ou um e-mail.", + "Share with other people by entering a user or group or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo ou um email.", "The server encountered an internal error and was unable to complete your request." : "O servidor encontrou um erro interno e não pode completar sua solicitação.", "Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report." : "Entre em contato com o administrador se este erro aparecer várias vezes. Inclua os detalhes técnicos abaixo no seu relatório.", "For information how to properly configure your server, please see the <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">documentation</a>." : "Para obter informações sobre como configurar corretamente o servidor, consulte a <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">documentação</a>.", diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 989442eee9c..dd6a9acde01 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -16,14 +16,14 @@ "Password reset is disabled" : "A redefinição de senha está desabilitada", "Couldn't reset password because the token is invalid" : "Não foi possível redefinir a senha porque o token é inválido", "Couldn't reset password because the token is expired" : "Não foi possível redefinir a senha porque o token expirou", - "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Não foi possível enviar e-mail de redefinição porque não há nenhum endereço de e-mail para este nome de usuário. Entre em contato com o administrador.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Não foi possível enviar email de redefinição porque não há nenhum endereço de email para este nome de usuário. Entre em contato com o administrador.", "%s password reset" : "%s redefinir senha", "Password reset" : "Redefinir a senha", - "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no botão abaixo para redefinir sua senha. Se você não solicitou isso, ignore este e-mail.", - "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no link abaixo para redefinir sua senha. Se você não solicitou isso, ignore este e-mail.", + "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no botão abaixo para redefinir sua senha. Se você não solicitou isso, ignore este email.", + "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Clique no link abaixo para redefinir sua senha. Se você não solicitou isso, ignore este email.", "Reset your password" : "Redefinir sua senha", - "Couldn't send reset email. Please contact your administrator." : "Não foi possível enviar o e-mail de redefinição. Por favor, contate o administrador.", - "Couldn't send reset email. Please make sure your username is correct." : "Não foi possível enviar o e-mail de redefinição. Verifique se o seu nome de usuário está correto.", + "Couldn't send reset email. Please contact your administrator." : "Não foi possível enviar o email de redefinição. Por favor, contate o administrador.", + "Couldn't send reset email. Please make sure your username is correct." : "Não foi possível enviar o email de redefinição. Verifique se o seu nome de usuário está correto.", "Preparing update" : "Preparando a atualização", "[%d / %d]: %s" : "[%d / %d]: %s", "Repair warning: " : "Aviso da reparação:", @@ -73,7 +73,7 @@ "Failed to authenticate, try again" : "Falha na autenticação, tente novamente", "seconds ago" : "segundos atrás", "Logging in …" : "Entrando...", - "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator." : "O link para redefinir sua senha foi enviado para seu e-mail. Se você não recebê-lo dentro de um período razoável de tempo, verifique suas pastas de spam/lixo.<br> Se ele não estiver lá, pergunte ao administrador local.", + "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator." : "O link para redefinir sua senha foi enviado para seu email. Se você não recebê-lo dentro de um período razoável de tempo, verifique suas pastas de spam/lixo.<br> Se ele não estiver lá, pergunte ao administrador local.", "Your files are encrypted. There will be no way to get your data back after your password is reset.<br />If you are not sure what to do, please contact your administrator before you continue. <br />Do you really want to continue?" : "Seus arquivos são criptografados. Não existe nenhuma maneira de ter seus dados de volta depois que sua senha seja redefinida.<br /> Se você não tem certeza do que fazer, por favor contate seu administrador antes de continuar.<br />Você realmente deseja continuar?", "I know what I'm doing" : "Eu sei o que estou fazendo", "Password can not be changed. Please contact your administrator." : "A senha não pôde ser alterada. Por favor, contate o administrador.", @@ -109,7 +109,7 @@ "Strong password" : "Senha forte", "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Seu servidor web ainda não está configurado corretamente para permitir a sincronização de arquivos, porque a interface do WebDAV parece estar quebrada.", "Your web server is not properly set up to resolve \"{url}\". Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "Seu servidor web não está configurado corretamente para resolver \"{url}\". Mais informações podem ser encontradas na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentação</a>.", - "This server has no working Internet connection: Multiple endpoints could not be reached. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. Establish a connection from this server to the Internet to enjoy all features." : "Este servidor não possui conexão com a internet: Vários pontos não puderam ser acessados. Isso significa que alguns dos recursos como montagem de armazenamento externo, notificações sobre atualizações ou instalação de aplicativos de terceiros não funcionarão. Acesso a arquivos remotos e envio de e-mails de notificação não funcionarão também. Estabeleça uma conexão deste servidor com a Internet para aproveitar todos os recursos.", + "This server has no working Internet connection: Multiple endpoints could not be reached. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. Establish a connection from this server to the Internet to enjoy all features." : "Este servidor não possui conexão com a internet: Vários pontos não puderam ser acessados. Isso significa que alguns dos recursos como montagem de armazenamento externo, notificações sobre atualizações ou instalação de aplicativos de terceiros não funcionarão. Acesso a arquivos remotos e envio de emails de notificação não funcionarão também. Estabeleça uma conexão deste servidor com a Internet para aproveitar todos os recursos.", "No memory cache has been configured. To enhance performance, please configure a memcache, if available. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "Nenhum cache de memória foi configurado. Para melhorar o desempenho, configure um memcache, se disponível. Mais informações podem ser encontradas na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentação</a>.", "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "/dev/urandom não é legível pelo PHP, o que é altamente desencorajado por razões de segurança. Mais informações podem ser encontradas na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentação</a>.", "You are currently running PHP {version}. Upgrade your PHP version to take advantage of <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{phpLink}\">performance and security updates provided by the PHP Group</a> as soon as your distribution supports it." : "Você está executando o PHP {versão}. Atualize esta versão para aproveitar as <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{phpLink}\">atualizações de desempenho e segurança fornecidas pelo Grupo PHP</a> assim que sua distribuição a suportar.", @@ -146,18 +146,18 @@ "Link" : "Link", "Password protect" : "Proteger com senha", "Allow editing" : "Permitir edição", - "Email link to person" : "Enviar link por e-mail", + "Email link to person" : "Enviar link por email", "Send" : "Enviar", "Allow upload and editing" : "Permitir envio e edição", "Read only" : "Somente leitura", "File drop (upload only)" : "Zona de arquivos (somente envio)", "Shared with you and the group {group} by {owner}" : "Compartilhado com você e com o grupo {group} por {owner}", "Shared with you by {owner}" : "Compartilhado com você por {owner}", - "Choose a password for the mail share" : "Escolha uma senha para o compartilhamento de e-mail", + "Choose a password for the mail share" : "Escolha uma senha para o compartilhamento de email", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatiorDisplayName}} compartilhou via link", "group" : "grupo", "remote" : "remoto", - "email" : "e-mail", + "email" : "email", "shared by {sharer}" : "compartilhado por {sharer}", "Unshare" : "Descompartilhar", "Can reshare" : "Pode compartilhar novamente", @@ -180,9 +180,9 @@ "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartilhar", - "Name or email address..." : "Nome ou endereço de e-mail...", + "Name or email address..." : "Nome ou endereço de email...", "Name or federated cloud ID..." : "Nome ou ID de cloud federada...", - "Name, federated cloud ID or email address..." : "Nome, ID de cloud federada ou e-mail...", + "Name, federated cloud ID or email address..." : "Nome, ID de cloud federada ou email...", "Name..." : "Nome...", "Error" : "Erro", "Error removing share" : "Erro na exclusão do compartilhamento", @@ -273,7 +273,7 @@ "Please contact your administrator." : "Por favor, contacte o administrador.", "An internal error occurred." : "Ocorreu um erro interno.", "Please try again or contact your administrator." : "Por favor tente novamente ou contacte o administrador.", - "Username or email" : "Nome de usuário ou e-mail", + "Username or email" : "Nome de usuário ou email", "Log in" : "Entrar", "Wrong password." : "Senha errada", "We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds." : "Detectamos várias tentativas de login inválidas de seu IP. Portanto, seu próximo login será desacelerado em até 30 segundos.", @@ -333,9 +333,9 @@ "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\" rel=\"noreferrer\">security tips</a>." : "O cabeçalho HTTP \"Strict-Transport-Security\" não está configurado para ao menos \"{seconds}\" segundos. Para uma segurança aprimorada, recomendamos habilitar HSTS como descrito em nossas <a href=\"{docUrl}\" rel=\"noreferrer\">dicas de segurança</a>.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our <a href=\"{docUrl}\">security tips</a>." : "Você está acessando este site via HTTP. Recomendamos que configure seu servidor para exigir o uso de HTTPS, conforme descrito em nossas <a href=\"{docUrl}\">dicas de segurança</a>.", "Shared with {recipients}" : "Compartilhado com {recipients}", - "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo, ID de cloud federada ou um e-mail.", + "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo, ID de cloud federada ou um email.", "Share with other people by entering a user or group or a federated cloud ID." : "Compartilhe com outras pessoas entrando um usuário, grupo ou ID de nuvem federada.", - "Share with other people by entering a user or group or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo ou um e-mail.", + "Share with other people by entering a user or group or an email address." : "Compartilhe com outras pessoas entrando um usuário, grupo ou um email.", "The server encountered an internal error and was unable to complete your request." : "O servidor encontrou um erro interno e não pode completar sua solicitação.", "Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report." : "Entre em contato com o administrador se este erro aparecer várias vezes. Inclua os detalhes técnicos abaixo no seu relatório.", "For information how to properly configure your server, please see the <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">documentation</a>." : "Para obter informações sobre como configurar corretamente o servidor, consulte a <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">documentação</a>.", diff --git a/core/l10n/ru.js b/core/l10n/ru.js index b17dbf8d8f5..80786d87d2c 100644 --- a/core/l10n/ru.js +++ b/core/l10n/ru.js @@ -264,8 +264,12 @@ OC.L10N.register( "See the documentation" : "Посмотреть документацию", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Для корректной работы приложения требуется JavaScript. Пожалуйста, {linkstart}включите JavaScript{linkend} и обновите страницу.", "More apps" : "Ещё приложения", + "More apps menu" : "Меню дополнительных приложений", "Search" : "Найти", "Reset search" : "Очистить поиск", + "Contacts" : "Контакты", + "Contacts menu" : "Меню контактов", + "Settings menu" : "Меню настроек", "Confirm your password" : "Подтвердите свой пароль", "Server side authentication failed!" : "Ошибка аутентификации на стороне сервера!", "Please contact your administrator." : "Пожалуйста, обратитесь к администратору.", diff --git a/core/l10n/ru.json b/core/l10n/ru.json index 31e2abb701e..f335d97924e 100644 --- a/core/l10n/ru.json +++ b/core/l10n/ru.json @@ -262,8 +262,12 @@ "See the documentation" : "Посмотреть документацию", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Для корректной работы приложения требуется JavaScript. Пожалуйста, {linkstart}включите JavaScript{linkend} и обновите страницу.", "More apps" : "Ещё приложения", + "More apps menu" : "Меню дополнительных приложений", "Search" : "Найти", "Reset search" : "Очистить поиск", + "Contacts" : "Контакты", + "Contacts menu" : "Меню контактов", + "Settings menu" : "Меню настроек", "Confirm your password" : "Подтвердите свой пароль", "Server side authentication failed!" : "Ошибка аутентификации на стороне сервера!", "Please contact your administrator." : "Пожалуйста, обратитесь к администратору.", diff --git a/core/l10n/tr.js b/core/l10n/tr.js index d7f70a83dce..8d2ae6833fd 100644 --- a/core/l10n/tr.js +++ b/core/l10n/tr.js @@ -264,8 +264,12 @@ OC.L10N.register( "See the documentation" : "Belgelere bakın", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Bu uygulamanın düzgün çalışabilmesi için JavaScript gereklidir. Lütfen {linkstart}JavaScript uygulamasını etkinleştirip{linkend} sayfayı yeniden yükleyin.", "More apps" : "Diğer uygulamalar", + "More apps menu" : "Diğer uygulamalar menüsü", "Search" : "Arama", "Reset search" : "Aramayı sıfırla", + "Contacts" : "Kişiler", + "Contacts menu" : "Kişiler menüsü", + "Settings menu" : "Ayarlar menüsü", "Confirm your password" : "Parolanızı onaylayın", "Server side authentication failed!" : "Kimlik sunucu tarafında doğrulanamadı!", "Please contact your administrator." : "Lütfen sistem yöneticiniz ile görüşün.", @@ -294,6 +298,7 @@ OC.L10N.register( "Error while validating your second factor" : "İkinci aşama doğrulanırken sorun çıktı", "Access through untrusted domain" : "Güvenilmeyen etki alanı üzerinden erişim", "Please contact your administrator. If you are an administrator, edit the \"trusted_domains\" setting in config/config.php like the example in config.sample.php." : "Lütfen yöneticiniz ile görüşün. Yöneticisi siz iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını config/config.sample.php dosyasındaki gibi düzenleyin.", + "Further information how to configure this can be found in the %sdocumentation%s." : "Bu ayar ile ilgili ayrıntılı bilgiler %sbelgeler%s bölümünde bulunabilir.", "App update required" : "Uygulamanın güncellenmesi gerekli", "%s will be updated to version %s" : "%s, %s sürümüne güncellenecek", "These apps will be updated:" : "Şu uygulamalar güncellenecek:", diff --git a/core/l10n/tr.json b/core/l10n/tr.json index 6e32e3ff3a8..e6ae26d7f45 100644 --- a/core/l10n/tr.json +++ b/core/l10n/tr.json @@ -262,8 +262,12 @@ "See the documentation" : "Belgelere bakın", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Bu uygulamanın düzgün çalışabilmesi için JavaScript gereklidir. Lütfen {linkstart}JavaScript uygulamasını etkinleştirip{linkend} sayfayı yeniden yükleyin.", "More apps" : "Diğer uygulamalar", + "More apps menu" : "Diğer uygulamalar menüsü", "Search" : "Arama", "Reset search" : "Aramayı sıfırla", + "Contacts" : "Kişiler", + "Contacts menu" : "Kişiler menüsü", + "Settings menu" : "Ayarlar menüsü", "Confirm your password" : "Parolanızı onaylayın", "Server side authentication failed!" : "Kimlik sunucu tarafında doğrulanamadı!", "Please contact your administrator." : "Lütfen sistem yöneticiniz ile görüşün.", @@ -292,6 +296,7 @@ "Error while validating your second factor" : "İkinci aşama doğrulanırken sorun çıktı", "Access through untrusted domain" : "Güvenilmeyen etki alanı üzerinden erişim", "Please contact your administrator. If you are an administrator, edit the \"trusted_domains\" setting in config/config.php like the example in config.sample.php." : "Lütfen yöneticiniz ile görüşün. Yöneticisi siz iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını config/config.sample.php dosyasındaki gibi düzenleyin.", + "Further information how to configure this can be found in the %sdocumentation%s." : "Bu ayar ile ilgili ayrıntılı bilgiler %sbelgeler%s bölümünde bulunabilir.", "App update required" : "Uygulamanın güncellenmesi gerekli", "%s will be updated to version %s" : "%s, %s sürümüne güncellenecek", "These apps will be updated:" : "Şu uygulamalar güncellenecek:", diff --git a/core/l10n/uk.js b/core/l10n/uk.js index 6b25eadd117..22bedcc5768 100644 --- a/core/l10n/uk.js +++ b/core/l10n/uk.js @@ -264,6 +264,7 @@ OC.L10N.register( "This page will refresh itself when the %s instance is available again." : "Ця сторінка автоматично перезавантажиться коли екземпляр %s стане знову доступний.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Зверніться до вашого системного адміністратора якщо це повідомлення не зникає або з'являється несподівано.", "Thank you for your patience." : "Дякуємо за ваше терпіння.", + "Wrong password. Reset it?" : "Невірний пароль. Скинути його?", "Stay logged in" : "Залишатись в системі", "Alternative Logins" : "Альтернативні імена користувача", "Add \"%s\" as trusted domain" : "Додати \"%s\" як довірений домен", diff --git a/core/l10n/uk.json b/core/l10n/uk.json index 0b2d4c28942..ee535456ab3 100644 --- a/core/l10n/uk.json +++ b/core/l10n/uk.json @@ -262,6 +262,7 @@ "This page will refresh itself when the %s instance is available again." : "Ця сторінка автоматично перезавантажиться коли екземпляр %s стане знову доступний.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Зверніться до вашого системного адміністратора якщо це повідомлення не зникає або з'являється несподівано.", "Thank you for your patience." : "Дякуємо за ваше терпіння.", + "Wrong password. Reset it?" : "Невірний пароль. Скинути його?", "Stay logged in" : "Залишатись в системі", "Alternative Logins" : "Альтернативні імена користувача", "Add \"%s\" as trusted domain" : "Додати \"%s\" як довірений домен", diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js index 0f292d3aac8..623ba939dbc 100644 --- a/lib/l10n/pt_BR.js +++ b/lib/l10n/pt_BR.js @@ -58,7 +58,7 @@ OC.L10N.register( "Empty filename is not allowed" : "Nome vazio para arquivo não é permitido.", "App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pôde ser lido.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "O aplicativo \"%s\" não pode ser instalado pois não é compatível com a versão do servidor.", - "This is an automatically sent email, please do not reply." : "Este é um e-mail enviado automaticamente. Por favor, não responda.", + "This is an automatically sent email, please do not reply." : "Este é um email enviado automaticamente. Por favor, não responda.", "Help" : "Ajuda", "Apps" : "Aplicativos", "Settings" : "Configurações", diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json index 62571d500a3..0eaeb8daaf0 100644 --- a/lib/l10n/pt_BR.json +++ b/lib/l10n/pt_BR.json @@ -56,7 +56,7 @@ "Empty filename is not allowed" : "Nome vazio para arquivo não é permitido.", "App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pôde ser lido.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "O aplicativo \"%s\" não pode ser instalado pois não é compatível com a versão do servidor.", - "This is an automatically sent email, please do not reply." : "Este é um e-mail enviado automaticamente. Por favor, não responda.", + "This is an automatically sent email, please do not reply." : "Este é um email enviado automaticamente. Por favor, não responda.", "Help" : "Ajuda", "Apps" : "Aplicativos", "Settings" : "Configurações", diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php index 304b2ccf464..d2232624b9b 100644 --- a/lib/private/Files/Node/Node.php +++ b/lib/private/Files/Node/Node.php @@ -265,7 +265,11 @@ class Node implements \OCP\Files\Node { * @return Node */ public function getParent() { - return $this->root->get(dirname($this->path)); + $newPath = dirname($this->path); + if ($newPath === '' || $newPath === '.' || $newPath === '/') { + return $this->root; + } + return $this->root->get($newPath); } /** diff --git a/lib/private/Files/ObjectStore/SwiftFactory.php b/lib/private/Files/ObjectStore/SwiftFactory.php index 8baaec985e8..3ff534b4e64 100644 --- a/lib/private/Files/ObjectStore/SwiftFactory.php +++ b/lib/private/Files/ObjectStore/SwiftFactory.php @@ -56,7 +56,7 @@ class SwiftFactory { private function getCachedToken(string $cacheKey) { $cachedTokenString = $this->cache->get($cacheKey . '/token'); if ($cachedTokenString) { - return json_decode($cachedTokenString); + return json_decode($cachedTokenString, true); } else { return null; } @@ -131,9 +131,9 @@ class SwiftFactory { $cachedToken = $this->params['cachedToken']; $hasValidCachedToken = false; - if (is_array($cachedToken)) { + if (\is_array($cachedToken) && ($authService instanceof IdentityV3Service)) { $token = $authService->generateTokenFromCache($cachedToken); - if (is_null($token->catalog)) { + if (\is_null($token->catalog)) { $this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken)); } else if ($token->hasExpired()) { $this->logger->debug('Cached token for swift expired'); diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index d3599d14e7a..356d336f687 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -259,6 +259,23 @@ class OC_Util { return $storage; }); + \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) { + /* + * Do not allow any operations that modify the storage + */ + if ($mount->getOption('readonly', false)) { + return new \OC\Files\Storage\Wrapper\PermissionsMask([ + 'storage' => $storage, + 'mask' => \OCP\Constants::PERMISSION_ALL & ~( + \OCP\Constants::PERMISSION_UPDATE | + \OCP\Constants::PERMISSION_CREATE | + \OCP\Constants::PERMISSION_DELETE + ), + ]); + } + return $storage; + }); + OC_Hook::emit('OC_Filesystem', 'preSetup', array('user' => $user)); \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(true); diff --git a/remote.php b/remote.php index 8879a300296..a14ff6ac308 100644 --- a/remote.php +++ b/remote.php @@ -100,6 +100,7 @@ function resolveService($service) { 'carddav' => 'dav/appinfo/v1/carddav.php', 'contacts' => 'dav/appinfo/v1/carddav.php', 'files' => 'dav/appinfo/v1/webdav.php', + 'direct' => 'dav/appinfo/v2/direct.php', ]; if (isset($services[$service])) { return $services[$service]; diff --git a/settings/l10n/ca.js b/settings/l10n/ca.js index 2c14150ac73..da1d8214c45 100644 --- a/settings/l10n/ca.js +++ b/settings/l10n/ca.js @@ -249,7 +249,7 @@ OC.L10N.register( "Enforce expiration date" : "Força la data de venciment", "Allow resharing" : "Permet compartir de nou", "Allow sharing with groups" : "Permetre compartir amb grups", - "Restrict users to only share with users in their groups" : "Permet als usuaris compartir només amb usuaris del seu grup", + "Restrict users to only share with users in their groups" : "Força als usuaris a compartir només amb usuaris del seu grup", "Exclude groups from sharing" : "Exclou grups de compartició", "These groups will still be able to receive shares, but not to initiate them." : "Aquests fitxers encara podran rebre compartits, però no podran iniciar-los.", "Tips & tricks" : "Consells i trucs", diff --git a/settings/l10n/ca.json b/settings/l10n/ca.json index 2a56b112582..dd51db3d6b8 100644 --- a/settings/l10n/ca.json +++ b/settings/l10n/ca.json @@ -247,7 +247,7 @@ "Enforce expiration date" : "Força la data de venciment", "Allow resharing" : "Permet compartir de nou", "Allow sharing with groups" : "Permetre compartir amb grups", - "Restrict users to only share with users in their groups" : "Permet als usuaris compartir només amb usuaris del seu grup", + "Restrict users to only share with users in their groups" : "Força als usuaris a compartir només amb usuaris del seu grup", "Exclude groups from sharing" : "Exclou grups de compartició", "These groups will still be able to receive shares, but not to initiate them." : "Aquests fitxers encara podran rebre compartits, però no podran iniciar-los.", "Tips & tricks" : "Consells i trucs", diff --git a/settings/l10n/de.js b/settings/l10n/de.js index 04684a26478..a14f26f8eb3 100644 --- a/settings/l10n/de.js +++ b/settings/l10n/de.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Gutes Passwort", "Strong password" : "Starkes Passwort", "Groups" : "Gruppen", + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Unable to delete {objName}" : "Löschen von {objName} nicht möglich", "Error creating group: {message}" : "Fehler beim Erstellen einer Gruppe: {message}", diff --git a/settings/l10n/de.json b/settings/l10n/de.json index 4a656faaada..132e71372b7 100644 --- a/settings/l10n/de.json +++ b/settings/l10n/de.json @@ -156,6 +156,7 @@ "Good password" : "Gutes Passwort", "Strong password" : "Starkes Passwort", "Groups" : "Gruppen", + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Unable to delete {objName}" : "Löschen von {objName} nicht möglich", "Error creating group: {message}" : "Fehler beim Erstellen einer Gruppe: {message}", diff --git a/settings/l10n/de_DE.js b/settings/l10n/de_DE.js index 60b245c0f3f..1ad4d0eeb64 100644 --- a/settings/l10n/de_DE.js +++ b/settings/l10n/de_DE.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Gutes Passwort", "Strong password" : "Starkes Passwort", "Groups" : "Gruppen", + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Unable to delete {objName}" : "Löschen von {objName} nicht möglich", "Error creating group: {message}" : "Fehler beim Erstellen einer Gruppe: {message}", diff --git a/settings/l10n/de_DE.json b/settings/l10n/de_DE.json index a7ceaeeeea3..a75e6074f3e 100644 --- a/settings/l10n/de_DE.json +++ b/settings/l10n/de_DE.json @@ -156,6 +156,7 @@ "Good password" : "Gutes Passwort", "Strong password" : "Starkes Passwort", "Groups" : "Gruppen", + "Group list is empty" : "Gruppenliste ist leer", "Unable to retrieve the group list" : "Gruppenliste konnte nicht empfangen werden", "Unable to delete {objName}" : "Löschen von {objName} nicht möglich", "Error creating group: {message}" : "Fehler beim Erstellen einer Gruppe: {message}", diff --git a/settings/l10n/es.js b/settings/l10n/es.js index 0c88eb2db34..da3d19f3607 100644 --- a/settings/l10n/es.js +++ b/settings/l10n/es.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Contraseña buena", "Strong password" : "Contraseña muy buena", "Groups" : "Grupos", + "Group list is empty" : "La lista del grupo está vacía", "Unable to retrieve the group list" : "No es posible recibir la lista de grupos", "Unable to delete {objName}" : "No es posible eliminar {objName}", "Error creating group: {message}" : "Error creando el grupo: {message}", diff --git a/settings/l10n/es.json b/settings/l10n/es.json index 580eda0a37e..1fc9c3f8f8a 100644 --- a/settings/l10n/es.json +++ b/settings/l10n/es.json @@ -156,6 +156,7 @@ "Good password" : "Contraseña buena", "Strong password" : "Contraseña muy buena", "Groups" : "Grupos", + "Group list is empty" : "La lista del grupo está vacía", "Unable to retrieve the group list" : "No es posible recibir la lista de grupos", "Unable to delete {objName}" : "No es posible eliminar {objName}", "Error creating group: {message}" : "Error creando el grupo: {message}", diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js index 7f600477ba8..9651b98ca69 100644 --- a/settings/l10n/fr.js +++ b/settings/l10n/fr.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Mot de passe de sécurité suffisante", "Strong password" : "Mot de passe de forte sécurité", "Groups" : "Groupes", + "Group list is empty" : "La liste du groupe est vide", "Unable to retrieve the group list" : "Impossible de récupérer la liste du groupe", "Unable to delete {objName}" : "Impossible de supprimer {objName}", "Error creating group: {message}" : "Erreur lors de la création du groupe : {message}", diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json index 840b1604b3f..01a29694417 100644 --- a/settings/l10n/fr.json +++ b/settings/l10n/fr.json @@ -156,6 +156,7 @@ "Good password" : "Mot de passe de sécurité suffisante", "Strong password" : "Mot de passe de forte sécurité", "Groups" : "Groupes", + "Group list is empty" : "La liste du groupe est vide", "Unable to retrieve the group list" : "Impossible de récupérer la liste du groupe", "Unable to delete {objName}" : "Impossible de supprimer {objName}", "Error creating group: {message}" : "Erreur lors de la création du groupe : {message}", diff --git a/settings/l10n/it.js b/settings/l10n/it.js index 165aeda3123..ac42b854db4 100644 --- a/settings/l10n/it.js +++ b/settings/l10n/it.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Password buona", "Strong password" : "Password forte", "Groups" : "Gruppi", + "Group list is empty" : "L'elenco dei gruppi è vuoto", "Unable to retrieve the group list" : "Impossibile recuperare l'elenco dei gruppi", "Unable to delete {objName}" : "Impossibile eliminare {objName}", "Error creating group: {message}" : "Errore durante la creazione del gruppo: {message}", diff --git a/settings/l10n/it.json b/settings/l10n/it.json index 94164fa25ec..63ad67f81b1 100644 --- a/settings/l10n/it.json +++ b/settings/l10n/it.json @@ -156,6 +156,7 @@ "Good password" : "Password buona", "Strong password" : "Password forte", "Groups" : "Gruppi", + "Group list is empty" : "L'elenco dei gruppi è vuoto", "Unable to retrieve the group list" : "Impossibile recuperare l'elenco dei gruppi", "Unable to delete {objName}" : "Impossibile eliminare {objName}", "Error creating group: {message}" : "Errore durante la creazione del gruppo: {message}", diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js index aa0f933dde1..d5d2b028996 100644 --- a/settings/l10n/pl.js +++ b/settings/l10n/pl.js @@ -75,6 +75,7 @@ OC.L10N.register( "Set your password" : "Ustaw hasło", "Go to %s" : "Idź do: %s", "Install Client" : "Zainstaluj klienta", + "Logged in user must be a subadmin" : "Zalogowany użytkownik musi być współadminem", "Password confirmation is required" : "Wymagane jest potwierdzenie hasła", "Couldn't remove app." : "Nie można usunąć aplikacji.", "Couldn't update app." : "Nie można uaktualnić aplikacji.", @@ -101,6 +102,8 @@ OC.L10N.register( "Error: Could not disable broken app" : "Błąd: Nie można wyłączyć uszkodzonej aplikacji", "Error while disabling broken app" : "Błąd podczas wyłączania uszkodzonej aplikacji", "App up to date" : "Aplikacja jest aktualna", + "Updating …" : "Aktualizowanie...", + "Could not update app" : "Nie można uaktualnić aplikacji.", "Updated" : "Zaktualizowano", "Removing …" : "Usuwanie ...", "Could not remove app" : "Usuwanie aplikacji nie powiodło się", @@ -155,6 +158,8 @@ OC.L10N.register( "Good password" : "Dobre hasło", "Strong password" : "Mocne hasło", "Groups" : "Grupy", + "Group list is empty" : "Lista grup jest pusta", + "Unable to retrieve the group list" : "Nie można pobrać listy grup", "Unable to delete {objName}" : "Nie można usunąć {objName}", "Error creating group: {message}" : "Błąd podczas tworzenia grupy: {message}", "A valid group name must be provided" : "Należy podać prawidłową nazwę grupy", @@ -387,6 +392,33 @@ OC.L10N.register( "A valid password must be provided" : "Należy podać prawidłowe hasło", "A valid email must be provided" : "Podaj poprawny adres email", "__language_name__" : "polski", + "Verifying" : "Weryfikacja", + "Personal info" : "Informacje osobiste", + "Sync clients" : "Klienci synchronizacji", + "It's important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the Tips & Ticks section and the documentation for more information." : "Poprawna konfiguracja jest ważna dla bezpieczeństwa i wydajności Twojej instancji. W celach pomocniczych przeprowadzane są automatyczne kontrole. Więcej informacji można znaleźć w dziale Wskazówki i Porady oraz w dokumentacji.", + "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "Wydaje się, że PHP nie jest prawidłowo ustawione, aby odpytać system o zmienne środowiskowe. Test getenv(\"PATH\") zwraca tylko puste odpowiedzi.", + "Please check the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">installation documentation ↗</a> for php configuration notes and the php configuration of your server, especially when using php-fpm." : "Prosze sprawdzić w <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentacji instalacji ↗</a> wpisy dotyczące konfiguracji PHP i konfiguracji PHP, kiedy używane jest php-fpm.", + "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "Wygląda na to, że ustawienia PHP ucinają bloki wklejonych dokumentów. To sprawi, że niektóre wbudowane aplikacje będą niedostępne.", + "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "Zainstalowana wersja %2$s jest starsza niż %1$s. Ze względów stabilności i wydajności zalecamy aktualizację do nowszej wersji %1$s.", + "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with MIME type detection." : "Brak modułu PHP „fileinfo”. Zalecamy włączenie tego modułu, aby uzyskać najlepsze wyniki podczas wykrywania typów MIME.", + "Transactional file locking is disabled, this might lead to issues with race conditions. Enable 'filelocking.enabled' in config.php to avoid these problems. See the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation ↗</a> for more information." : "Transakcyjne blokowanie plików jest wyłączone. Może to powodować problemy w działaniu. Włącz 'filelocking.enabled' w config.php, aby rozwiązać te problemy. Sprawdź <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentację ↗</a>, aby uzyskać więcej informacji.", + "This means that there might be problems with certain characters in file names." : "Oznacza to, że mogą być problemy z niektórymi znakami w nazwach plików.", + "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "Zalecamy instalację na Twoim systemie komponentów wymaganych do obsługi języków: %s", + "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Jeśli twoja instalacja nie jest zainstalowana w katalogu root domeny i używa systemowego crona, mogą wystąpić problemy z tworzeniem adresów URL. Aby rozwiązać ten problem, proszę ustawić w swoim pliku config.php opcję \"overwrite.cli.url\" wskazując ścieżkę instalacji (sugerujemy: \"%s\")", + "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Nie było możliwe do wykonania przez cron CLI. Pojawiły się następujące błędy techniczne:", + "Please double check the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"%s\">log</a>." : "Proszę sprawdzić dokładnie <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">przewodniki instalacji ↗</a> oraz błędy i ostrzeżenia w <a href=\"%s\">logu</a>.", + "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "Wywołanie cron.php jest ustawione jako usługa webcron co 15 minut przez protokół HTTP.", + "To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "Aby to uruchomić potrzebujesz rozszerzenia posix do PHP. Po więcej informacji sprawdź {linkstart}dokumentację PHP{linkend}.", + "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation ↗</a>." : "Aby zmigrować do innej bazy danych użyj narzędzia z terminala: \"occ db:convert-type\" albo sprawdź <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentację ↗</a>.", + "Get the apps to sync your files" : "Pobierz aplikacje aby zsynchronizować swoje pliki", + "Desktop client" : "Klient na komputer", + "Android app" : "Aplikacja Android", + "iOS app" : "Aplikacja iOS", + "If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!" : "Jeśli chcesz wesprzeć projekt {contributeopen}dołącz do twórców{linkclose} lub {contributeopen}głoś dobre słowo{linkclose}!", + "Show First Run Wizard again" : "Pokaż ponownie Kreator pierwszego uruchomienia", + "Web, desktop, mobile clients and app specific passwords that currently have access to your account." : "Lista urządzeń, które mają dostęp do Twojego konta wraz z utworzonymi hasłami dostępu - w tym klienci przeglądarek web, aplikacje desktopowe i mobilne.", + "App passwords" : "Hasła aplikacji", + "Here you can generate individual passwords for apps so you don’t have to give out your password. You can revoke them individually too." : "Tutaj możesz wygenerować lub unieważnić hasła dla poszczególnych aplikacji tak, aby nie było potrzeby podawania Twojego hasła. ", "Follow us on Google+!" : "Bądź z nami na Google+!", "Like our facebook page!" : "Polub naszą stronę na Facebooku!", "Follow us on Twitter!" : "Bądź z nami na Twitterze!", diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json index 153166cdcbe..96abc548de4 100644 --- a/settings/l10n/pl.json +++ b/settings/l10n/pl.json @@ -73,6 +73,7 @@ "Set your password" : "Ustaw hasło", "Go to %s" : "Idź do: %s", "Install Client" : "Zainstaluj klienta", + "Logged in user must be a subadmin" : "Zalogowany użytkownik musi być współadminem", "Password confirmation is required" : "Wymagane jest potwierdzenie hasła", "Couldn't remove app." : "Nie można usunąć aplikacji.", "Couldn't update app." : "Nie można uaktualnić aplikacji.", @@ -99,6 +100,8 @@ "Error: Could not disable broken app" : "Błąd: Nie można wyłączyć uszkodzonej aplikacji", "Error while disabling broken app" : "Błąd podczas wyłączania uszkodzonej aplikacji", "App up to date" : "Aplikacja jest aktualna", + "Updating …" : "Aktualizowanie...", + "Could not update app" : "Nie można uaktualnić aplikacji.", "Updated" : "Zaktualizowano", "Removing …" : "Usuwanie ...", "Could not remove app" : "Usuwanie aplikacji nie powiodło się", @@ -153,6 +156,8 @@ "Good password" : "Dobre hasło", "Strong password" : "Mocne hasło", "Groups" : "Grupy", + "Group list is empty" : "Lista grup jest pusta", + "Unable to retrieve the group list" : "Nie można pobrać listy grup", "Unable to delete {objName}" : "Nie można usunąć {objName}", "Error creating group: {message}" : "Błąd podczas tworzenia grupy: {message}", "A valid group name must be provided" : "Należy podać prawidłową nazwę grupy", @@ -385,6 +390,33 @@ "A valid password must be provided" : "Należy podać prawidłowe hasło", "A valid email must be provided" : "Podaj poprawny adres email", "__language_name__" : "polski", + "Verifying" : "Weryfikacja", + "Personal info" : "Informacje osobiste", + "Sync clients" : "Klienci synchronizacji", + "It's important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the Tips & Ticks section and the documentation for more information." : "Poprawna konfiguracja jest ważna dla bezpieczeństwa i wydajności Twojej instancji. W celach pomocniczych przeprowadzane są automatyczne kontrole. Więcej informacji można znaleźć w dziale Wskazówki i Porady oraz w dokumentacji.", + "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "Wydaje się, że PHP nie jest prawidłowo ustawione, aby odpytać system o zmienne środowiskowe. Test getenv(\"PATH\") zwraca tylko puste odpowiedzi.", + "Please check the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">installation documentation ↗</a> for php configuration notes and the php configuration of your server, especially when using php-fpm." : "Prosze sprawdzić w <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentacji instalacji ↗</a> wpisy dotyczące konfiguracji PHP i konfiguracji PHP, kiedy używane jest php-fpm.", + "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "Wygląda na to, że ustawienia PHP ucinają bloki wklejonych dokumentów. To sprawi, że niektóre wbudowane aplikacje będą niedostępne.", + "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "Zainstalowana wersja %2$s jest starsza niż %1$s. Ze względów stabilności i wydajności zalecamy aktualizację do nowszej wersji %1$s.", + "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with MIME type detection." : "Brak modułu PHP „fileinfo”. Zalecamy włączenie tego modułu, aby uzyskać najlepsze wyniki podczas wykrywania typów MIME.", + "Transactional file locking is disabled, this might lead to issues with race conditions. Enable 'filelocking.enabled' in config.php to avoid these problems. See the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation ↗</a> for more information." : "Transakcyjne blokowanie plików jest wyłączone. Może to powodować problemy w działaniu. Włącz 'filelocking.enabled' w config.php, aby rozwiązać te problemy. Sprawdź <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentację ↗</a>, aby uzyskać więcej informacji.", + "This means that there might be problems with certain characters in file names." : "Oznacza to, że mogą być problemy z niektórymi znakami w nazwach plików.", + "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "Zalecamy instalację na Twoim systemie komponentów wymaganych do obsługi języków: %s", + "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Jeśli twoja instalacja nie jest zainstalowana w katalogu root domeny i używa systemowego crona, mogą wystąpić problemy z tworzeniem adresów URL. Aby rozwiązać ten problem, proszę ustawić w swoim pliku config.php opcję \"overwrite.cli.url\" wskazując ścieżkę instalacji (sugerujemy: \"%s\")", + "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Nie było możliwe do wykonania przez cron CLI. Pojawiły się następujące błędy techniczne:", + "Please double check the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"%s\">log</a>." : "Proszę sprawdzić dokładnie <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">przewodniki instalacji ↗</a> oraz błędy i ostrzeżenia w <a href=\"%s\">logu</a>.", + "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "Wywołanie cron.php jest ustawione jako usługa webcron co 15 minut przez protokół HTTP.", + "To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "Aby to uruchomić potrzebujesz rozszerzenia posix do PHP. Po więcej informacji sprawdź {linkstart}dokumentację PHP{linkend}.", + "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation ↗</a>." : "Aby zmigrować do innej bazy danych użyj narzędzia z terminala: \"occ db:convert-type\" albo sprawdź <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentację ↗</a>.", + "Get the apps to sync your files" : "Pobierz aplikacje aby zsynchronizować swoje pliki", + "Desktop client" : "Klient na komputer", + "Android app" : "Aplikacja Android", + "iOS app" : "Aplikacja iOS", + "If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!" : "Jeśli chcesz wesprzeć projekt {contributeopen}dołącz do twórców{linkclose} lub {contributeopen}głoś dobre słowo{linkclose}!", + "Show First Run Wizard again" : "Pokaż ponownie Kreator pierwszego uruchomienia", + "Web, desktop, mobile clients and app specific passwords that currently have access to your account." : "Lista urządzeń, które mają dostęp do Twojego konta wraz z utworzonymi hasłami dostępu - w tym klienci przeglądarek web, aplikacje desktopowe i mobilne.", + "App passwords" : "Hasła aplikacji", + "Here you can generate individual passwords for apps so you don’t have to give out your password. You can revoke them individually too." : "Tutaj możesz wygenerować lub unieważnić hasła dla poszczególnych aplikacji tak, aby nie było potrzeby podawania Twojego hasła. ", "Follow us on Google+!" : "Bądź z nami na Google+!", "Like our facebook page!" : "Polub naszą stronę na Facebooku!", "Follow us on Twitter!" : "Bądź z nami na Twitterze!", diff --git a/settings/l10n/pt_BR.js b/settings/l10n/pt_BR.js index 19f7f615379..062b4f2d448 100644 --- a/settings/l10n/pt_BR.js +++ b/settings/l10n/pt_BR.js @@ -4,13 +4,13 @@ OC.L10N.register( "{actor} changed your password" : "{actor} alterou sua senha", "You changed your password" : "Você alterou sua senha", "Your password was reset by an administrator" : "Sua senha foi redefinida pelo administrador", - "{actor} changed your email address" : "{actor} alterou seu endereço de e-mail", - "You changed your email address" : "Você alterou seu e-mail", - "Your email address was changed by an administrator" : "Seu e-mail foi alterado pelo administrador", + "{actor} changed your email address" : "{actor} alterou seu endereço de email", + "You changed your email address" : "Você alterou seu email", + "Your email address was changed by an administrator" : "Seu email foi alterado pelo administrador", "Security" : "Segurança", "You successfully logged in using two-factor authentication (%1$s)" : "Você conectou com sucesso usando a autenticação de dois fatores (%1$s)", "A login attempt using two-factor authentication failed (%1$s)" : "A tentativa de login usando autenticação de dois fatores falhou (%1$s)", - "Your <strong>password</strong> or <strong>email</strong> was modified" : "Sua <strong>senha</strong> ou <strong>e-mail</strong> foram alterados", + "Your <strong>password</strong> or <strong>email</strong> was modified" : "Sua <strong>senha</strong> ou <strong>email</strong> foram alterados", "Your apps" : "Seus aplicativos", "Updates" : "Atualizações", "Enabled apps" : "Aplicativos habilitados", @@ -31,16 +31,16 @@ OC.L10N.register( "Unable to add group." : "Não foi possível adicionar o grupo.", "Unable to delete group." : "Não foi possível excluir o grupo.", "Invalid SMTP password." : "Senha SMTP incorreta.", - "Email setting test" : "Teste da configuração de e-mail", + "Email setting test" : "Teste da configuração de email", "Well done, %s!" : "Bom trabalho %s!", - "If you received this email, the email configuration seems to be correct." : "Se você recebeu este e-mail, é sinal que a configuração do servidor de e-mail está correta.", - "Email could not be sent. Check your mail server log" : "O e-mail não pôde ser enviado. Verifique o log do servidor de e-mail", - "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Ocorreu um problema ao enviar o e-mail. Por favor, revise suas configurações. (Erro: %s)", - "You need to set your user email before being able to send test emails." : "Você precisa configurar seu e-mail de usuário antes de ser capaz de enviar e-mails de teste.", - "Invalid mail address" : "Endereço de e-mail inválido", + "If you received this email, the email configuration seems to be correct." : "Se você recebeu este email, é sinal que a configuração do servidor de email está correta.", + "Email could not be sent. Check your mail server log" : "O email não pôde ser enviado. Verifique o log do servidor de email", + "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Ocorreu um problema ao enviar o email. Por favor, revise suas configurações. (Erro: %s)", + "You need to set your user email before being able to send test emails." : "Você precisa configurar seu email de usuário antes de ser capaz de enviar emails de teste.", + "Invalid mail address" : "Endereço de email inválido", "No valid group selected" : "Nenhum grupo válido foi selecionado", "A user with that name already exists." : "Um usuário com esse nome já existe.", - "To send a password link to the user an email address is required." : "Para envio da senha ao usuário é necessário um endereço de e-mail.", + "To send a password link to the user an email address is required." : "Para envio da senha ao usuário é necessário um endereço de email.", "Unable to create user." : "Não foi possível criar usuário.", "Unable to delete user." : "Não é possível excluir o usuário.", "Error while enabling user." : "Erro ao habilitar usuário.", @@ -49,24 +49,24 @@ OC.L10N.register( "In order to verify your Website, store the following content in your web-root at '.well-known/CloudIdVerificationCode.txt' (please make sure that the complete text is in one line):" : "A fim de verificar seu Website, armazene o seguinte conteúdo na página raiz em '.well-known/CloudIdVerificationCode.txt' (certifique-se que o texto inteiro esteja em uma só linha):", "Settings saved" : "Configurações salvas", "Unable to change full name" : "Não foi possível alterar o nome completo", - "Unable to change email address" : "Não foi possível alterar o endereço de e-mail", + "Unable to change email address" : "Não foi possível alterar o endereço de email", "Your full name has been changed." : "Seu nome completo foi alterado.", "Forbidden" : "Proibido", "Invalid user" : "Usuário inválido", - "Unable to change mail address" : "Não foi possível alterar o endereço de e-mail", - "Email saved" : "E-mail salvo", + "Unable to change mail address" : "Não foi possível alterar o endereço de email", + "Email saved" : "Email salvo", "%1$s changed your password on %2$s." : "%1$s mudou sua senha em %2$s.", "Your password on %s was changed." : "Sua senha em %s foi alterada.", "Your password on %s was reset by an administrator." : "Sua senha em %s foi redefinida por um administrador.", "Password for %1$s changed on %2$s" : "Senha para %1$s alterada em %2$s", "Password changed for %s" : "Senha alterada para %s", "If you did not request this, please contact an administrator." : "Se você não solicitou isso, por favor contacte o administrador.", - "%1$s changed your email address on %2$s." : "%1$s alterou seu e-mail em %2$s.", - "Your email address on %s was changed." : "Seu e-mail em %s foi alterado.", - "Your email address on %s was changed by an administrator." : "Seu e-mail em %s foi alterado por um administrador.", - "Email address for %1$s changed on %2$s" : "O endereço de E-mail para %1$s foi alterado em %2$s", - "Email address changed for %s" : "E-mail alterado para %s", - "The new email address is %s" : "O novo e-mail é %s", + "%1$s changed your email address on %2$s." : "%1$s alterou seu email em %2$s.", + "Your email address on %s was changed." : "Seu email em %s foi alterado.", + "Your email address on %s was changed by an administrator." : "Seu email em %s foi alterado por um administrador.", + "Email address for %1$s changed on %2$s" : "O endereço de Email para %1$s foi alterado em %2$s", + "Email address changed for %s" : "Email alterado para %s", + "The new email address is %s" : "O novo email é %s", "Your %s account was created" : "Sua conta %s foi criada", "Welcome aboard" : "Bem-vindo a bordo", "Welcome aboard %s" : "%s, bem-vindo a bordo", @@ -83,7 +83,7 @@ OC.L10N.register( "Migration started …" : "Migração iniciada...", "Not saved" : "Não salvo", "Sending…" : "Enviando...", - "Email sent" : "E-mail enviado", + "Email sent" : "Email enviado", "Official" : "Oficial", "All" : "Todos", "Update to %s" : "Atualizar para %s", @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Boa senha", "Strong password" : "Senha forte", "Groups" : "Grupos", + "Group list is empty" : "Lista de grupos vazia", "Unable to retrieve the group list" : "Impossível recuperar a lista do grupo", "Unable to delete {objName}" : "Não foi possível excluir {objName}", "Error creating group: {message}" : "Erro criando o grupo: {message}", @@ -175,7 +176,7 @@ OC.L10N.register( "no group" : "nenhum grupo", "Password successfully changed" : "Senha alterada com sucesso", "Changing the password will result in data loss, because data recovery is not available for this user" : "Alterar a senha irá resultar em perda de dados pois a recuperação de dados não está disponível para este usuário", - "Could not change the users email" : "Não foi possível alterar o e-mail dos usuários", + "Could not change the users email" : "Não foi possível alterar o email dos usuários", "Error while changing status of {user}" : "Erro ao mudar o status de {user}", "A valid username must be provided" : "Forneça um nome de usuário válido", "Error creating user: {message}" : "Erro criando o usuário: {message}", @@ -213,13 +214,13 @@ OC.L10N.register( "NT LAN Manager" : "Gerenciador NT LAN", "SSL/TLS" : "SSL/TLS", "STARTTLS" : "STARTTLS", - "Email server" : "Servidor de e-mail", + "Email server" : "Servidor de email", "Open documentation" : "Abrir documentação", - "It is important to set up this server to be able to send emails, like for password reset and notifications." : "É importante configurar este servidor para poder enviar e-mails, assim como para redefinir a senha e notificações.", + "It is important to set up this server to be able to send emails, like for password reset and notifications." : "É importante configurar este servidor para poder enviar emails para redefinir a senha e notificações.", "Send mode" : "Modo de envio", "Encryption" : "Criptografia", "From address" : "Endereço \"From\"", - "mail" : "e-mail", + "mail" : "email", "Authentication method" : "Método de autenticação", "Authentication required" : "Autenticação é requerida", "Server address" : "Endereço do servidor", @@ -228,10 +229,10 @@ OC.L10N.register( "SMTP Username" : "Nome do Usuário SMTP", "SMTP Password" : "Senha SMTP", "Store credentials" : "Armazenar credenciais", - "Test email settings" : "Configurações do e-mail de teste", - "Send email" : "Enviar e-mail", + "Test email settings" : "Configurações do email de teste", + "Send email" : "Enviar email", "Server-side encryption" : "Criptografia do lado do servidor", - "Server-side encryption makes it possible to encrypt files which are uploaded to this server. This comes with limitations like a performance penalty, so enable this only if needed." : "A criptografia do lado do servidor torna possível criptografar arquivos que são carregados para este servidor. Isso diminui um pouco o desempenho, portanto habilite apenas se necessário.", + "Server-side encryption makes it possible to encrypt files which are uploaded to this server. This comes with limitations like a performance penalty, so enable this only if needed." : "A criptografia do lado do servidor torna possível criptografar arquivos que são carregados para este servidor. Isso diminui um pouco o desempenho portanto habilite apenas se necessário.", "Enable server-side encryption" : "Habilitar a criptografia do lado do servidor", "Please read carefully before activating server-side encryption: " : "Por favor, leia com atenção antes de ativar a criptografia do lado do servidor:", "Once encryption is enabled, all files uploaded to the server from that point forward will be encrypted at rest on the server. It will only be possible to disable encryption at a later date if the active encryption module supports that function, and all pre-conditions (e.g. setting a recover key) are met." : "Uma vez que a criptografia é ativada, todos os arquivos enviados ao servidor a partir desse ponto em diante serão criptografados e assim ficarão no servidor. Só será possível desativar a criptografia em uma data posterior se o módulo de criptografia ativo suportar essa função e todas as pré-condições sejam cumpridas (ex., defininindo uma chave de recuperação).", @@ -295,7 +296,7 @@ OC.L10N.register( "This text will be shown on the public link upload page when the file list is hidden." : "Este texto será mostrado na página de envio do link público quando a lista de arquivos está oculta.", "Default share permissions" : "Permissões padrão de compartilhamento", "Tips & tricks" : "Dicas & Truques", - "There are a lot of features and config switches available to optimally customize and use this instance. Here are some pointers for more information." : "Há muitos recursos e opções de configuração para otimização e uso. Aqui estão algumas indicações para obter mais informações.", + "There are a lot of features and config switches available to optimally customize and use this instance. Here are some pointers for more information." : "Há muitos recursos e opções de configuração para otimização e uso. Aqui estão algumas indicações para obter mais informações:", "SQLite is currently being used as the backend database. For larger installations we recommend that you switch to a different database backend." : "SQLite é usando atualmente como Plataforma de serviço de banco de dados. Para instalações maiores recomendamos que você use uma outra plataforma de serviço de banco de dados", "This is particularly recommended when using the desktop client for file synchronisation." : "Isso é particulamente recomendado quando se utiliza um cliente para sincronização.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation ↗</a>." : "Para migrar a outro banco de dados, use a ferramenta de linha de comando: 'occ db:convert-type', ou leia na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentação ↗</a> como fazer isso.", @@ -320,9 +321,9 @@ OC.L10N.register( "You are member of the following groups:" : "Você é membro dos seguintes grupos:", "Full name" : "Nome completo", "No display name set" : "Nenhum nome de exibição definido", - "Email" : "E-mail", - "Your email address" : "Seu endereço de e-mail", - "No email address set" : "Nenhum endereço de e-mail foi configurado", + "Email" : "Email", + "Your email address" : "Seu endereço de email", + "No email address set" : "Nenhum endereço de email foi configurado", "For password reset and notifications" : "Para redefinição de senha e notificações", "Phone number" : "Número de telefone", "Your phone number" : "Seu número de telefone", @@ -343,7 +344,7 @@ OC.L10N.register( "Device" : "Dispositivo", "Last activity" : "Última atividade", "App name" : "Nome do aplicativo", - "Create new app password" : "Criar uma nova senha do aplicativo", + "Create new app password" : "Criar nova senha de aplicativo", "Use the credentials below to configure your app or device." : "Use as credenciais abaixo para configurar seu aplicativo ou dispositivo.", "For security reasons this password will only be shown once." : "Por motivo de segurança, esta senha só será exibida uma vez.", "Username" : "Nome de Usuário", @@ -358,7 +359,7 @@ OC.L10N.register( "Show storage location" : "Mostrar localização do armazenamento", "Show user backend" : "Mostrar plataforma de serviço de usuário", "Show last login" : "Mostrar último login", - "When the password of a new user is left empty, an activation email with a link to set the password is sent." : "Quando a senha de um novo usuário é deixada em branco, um e-mail de ativação com um link para definir a senha é enviado.", + "When the password of a new user is left empty, an activation email with a link to set the password is sent." : "Quando a senha de um novo usuário é deixada em branco, um email de ativação com um link para definir a senha é enviado.", "Add user" : "Adicionar usuário", "Everyone" : "Para todos", "Admins" : "Administradores", @@ -373,12 +374,12 @@ OC.L10N.register( "Storage location" : "Local do armazenamento", "User backend" : "Plataforma de serviço de usuário", "Last login" : "Último acesso", - "E-Mail" : "E-mail", + "E-Mail" : "Email", "Admin Recovery Password" : "Senha de recuperação do administrador", "Enter the recovery password in order to recover the users files during password change" : "Digite a senha de recuperação para recuperar os arquivos dos usuários durante a mudança de senha.", "change full name" : "alterar nome completo", "set new password" : "definir uma senha nova", - "change email address" : "Alterar o endereço de e-mail", + "change email address" : "Alterar o endereço de email", "Default" : "Padrão", "A problem occurred, please check your log files (Error: %s)" : "Ocorreu um problema, por favor verifique seus arquivos de log (Erro: %s)", "Migration Completed" : "Migração concluída", @@ -389,7 +390,7 @@ OC.L10N.register( "Error while updating app" : "Erro ao atualizar aplicativo", "Error while removing app" : "Erro ao excluir aplicativo", "A valid password must be provided" : "Forneça uma senha válida", - "A valid email must be provided" : "Um e-mail válido deve ser fornecido", + "A valid email must be provided" : "Um email válido deve ser fornecido", "__language_name__" : "Português Brasileiro", "Verifying" : "Verificando", "Personal info" : "Informação pessoal", @@ -423,8 +424,8 @@ OC.L10N.register( "Follow us on Twitter!" : "Siga-nos no Twitter!", "Check out our blog!" : "Confira nosso blog!", "Subscribe to our newsletter!" : "Assine nosso boletim de notícias!", - "Show email address" : "Mostrar o endereço de e-mail", - "Send email to new user" : "Enviar um e-mail para o novo usuário", + "Show email address" : "Mostrar o endereço de email", + "Send email to new user" : "Enviar um email para o novo usuário", "Create" : "Criar", "Group name" : "Nome do grupo" }, diff --git a/settings/l10n/pt_BR.json b/settings/l10n/pt_BR.json index df61c5aea32..355eb0f5d63 100644 --- a/settings/l10n/pt_BR.json +++ b/settings/l10n/pt_BR.json @@ -2,13 +2,13 @@ "{actor} changed your password" : "{actor} alterou sua senha", "You changed your password" : "Você alterou sua senha", "Your password was reset by an administrator" : "Sua senha foi redefinida pelo administrador", - "{actor} changed your email address" : "{actor} alterou seu endereço de e-mail", - "You changed your email address" : "Você alterou seu e-mail", - "Your email address was changed by an administrator" : "Seu e-mail foi alterado pelo administrador", + "{actor} changed your email address" : "{actor} alterou seu endereço de email", + "You changed your email address" : "Você alterou seu email", + "Your email address was changed by an administrator" : "Seu email foi alterado pelo administrador", "Security" : "Segurança", "You successfully logged in using two-factor authentication (%1$s)" : "Você conectou com sucesso usando a autenticação de dois fatores (%1$s)", "A login attempt using two-factor authentication failed (%1$s)" : "A tentativa de login usando autenticação de dois fatores falhou (%1$s)", - "Your <strong>password</strong> or <strong>email</strong> was modified" : "Sua <strong>senha</strong> ou <strong>e-mail</strong> foram alterados", + "Your <strong>password</strong> or <strong>email</strong> was modified" : "Sua <strong>senha</strong> ou <strong>email</strong> foram alterados", "Your apps" : "Seus aplicativos", "Updates" : "Atualizações", "Enabled apps" : "Aplicativos habilitados", @@ -29,16 +29,16 @@ "Unable to add group." : "Não foi possível adicionar o grupo.", "Unable to delete group." : "Não foi possível excluir o grupo.", "Invalid SMTP password." : "Senha SMTP incorreta.", - "Email setting test" : "Teste da configuração de e-mail", + "Email setting test" : "Teste da configuração de email", "Well done, %s!" : "Bom trabalho %s!", - "If you received this email, the email configuration seems to be correct." : "Se você recebeu este e-mail, é sinal que a configuração do servidor de e-mail está correta.", - "Email could not be sent. Check your mail server log" : "O e-mail não pôde ser enviado. Verifique o log do servidor de e-mail", - "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Ocorreu um problema ao enviar o e-mail. Por favor, revise suas configurações. (Erro: %s)", - "You need to set your user email before being able to send test emails." : "Você precisa configurar seu e-mail de usuário antes de ser capaz de enviar e-mails de teste.", - "Invalid mail address" : "Endereço de e-mail inválido", + "If you received this email, the email configuration seems to be correct." : "Se você recebeu este email, é sinal que a configuração do servidor de email está correta.", + "Email could not be sent. Check your mail server log" : "O email não pôde ser enviado. Verifique o log do servidor de email", + "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Ocorreu um problema ao enviar o email. Por favor, revise suas configurações. (Erro: %s)", + "You need to set your user email before being able to send test emails." : "Você precisa configurar seu email de usuário antes de ser capaz de enviar emails de teste.", + "Invalid mail address" : "Endereço de email inválido", "No valid group selected" : "Nenhum grupo válido foi selecionado", "A user with that name already exists." : "Um usuário com esse nome já existe.", - "To send a password link to the user an email address is required." : "Para envio da senha ao usuário é necessário um endereço de e-mail.", + "To send a password link to the user an email address is required." : "Para envio da senha ao usuário é necessário um endereço de email.", "Unable to create user." : "Não foi possível criar usuário.", "Unable to delete user." : "Não é possível excluir o usuário.", "Error while enabling user." : "Erro ao habilitar usuário.", @@ -47,24 +47,24 @@ "In order to verify your Website, store the following content in your web-root at '.well-known/CloudIdVerificationCode.txt' (please make sure that the complete text is in one line):" : "A fim de verificar seu Website, armazene o seguinte conteúdo na página raiz em '.well-known/CloudIdVerificationCode.txt' (certifique-se que o texto inteiro esteja em uma só linha):", "Settings saved" : "Configurações salvas", "Unable to change full name" : "Não foi possível alterar o nome completo", - "Unable to change email address" : "Não foi possível alterar o endereço de e-mail", + "Unable to change email address" : "Não foi possível alterar o endereço de email", "Your full name has been changed." : "Seu nome completo foi alterado.", "Forbidden" : "Proibido", "Invalid user" : "Usuário inválido", - "Unable to change mail address" : "Não foi possível alterar o endereço de e-mail", - "Email saved" : "E-mail salvo", + "Unable to change mail address" : "Não foi possível alterar o endereço de email", + "Email saved" : "Email salvo", "%1$s changed your password on %2$s." : "%1$s mudou sua senha em %2$s.", "Your password on %s was changed." : "Sua senha em %s foi alterada.", "Your password on %s was reset by an administrator." : "Sua senha em %s foi redefinida por um administrador.", "Password for %1$s changed on %2$s" : "Senha para %1$s alterada em %2$s", "Password changed for %s" : "Senha alterada para %s", "If you did not request this, please contact an administrator." : "Se você não solicitou isso, por favor contacte o administrador.", - "%1$s changed your email address on %2$s." : "%1$s alterou seu e-mail em %2$s.", - "Your email address on %s was changed." : "Seu e-mail em %s foi alterado.", - "Your email address on %s was changed by an administrator." : "Seu e-mail em %s foi alterado por um administrador.", - "Email address for %1$s changed on %2$s" : "O endereço de E-mail para %1$s foi alterado em %2$s", - "Email address changed for %s" : "E-mail alterado para %s", - "The new email address is %s" : "O novo e-mail é %s", + "%1$s changed your email address on %2$s." : "%1$s alterou seu email em %2$s.", + "Your email address on %s was changed." : "Seu email em %s foi alterado.", + "Your email address on %s was changed by an administrator." : "Seu email em %s foi alterado por um administrador.", + "Email address for %1$s changed on %2$s" : "O endereço de Email para %1$s foi alterado em %2$s", + "Email address changed for %s" : "Email alterado para %s", + "The new email address is %s" : "O novo email é %s", "Your %s account was created" : "Sua conta %s foi criada", "Welcome aboard" : "Bem-vindo a bordo", "Welcome aboard %s" : "%s, bem-vindo a bordo", @@ -81,7 +81,7 @@ "Migration started …" : "Migração iniciada...", "Not saved" : "Não salvo", "Sending…" : "Enviando...", - "Email sent" : "E-mail enviado", + "Email sent" : "Email enviado", "Official" : "Oficial", "All" : "Todos", "Update to %s" : "Atualizar para %s", @@ -156,6 +156,7 @@ "Good password" : "Boa senha", "Strong password" : "Senha forte", "Groups" : "Grupos", + "Group list is empty" : "Lista de grupos vazia", "Unable to retrieve the group list" : "Impossível recuperar a lista do grupo", "Unable to delete {objName}" : "Não foi possível excluir {objName}", "Error creating group: {message}" : "Erro criando o grupo: {message}", @@ -173,7 +174,7 @@ "no group" : "nenhum grupo", "Password successfully changed" : "Senha alterada com sucesso", "Changing the password will result in data loss, because data recovery is not available for this user" : "Alterar a senha irá resultar em perda de dados pois a recuperação de dados não está disponível para este usuário", - "Could not change the users email" : "Não foi possível alterar o e-mail dos usuários", + "Could not change the users email" : "Não foi possível alterar o email dos usuários", "Error while changing status of {user}" : "Erro ao mudar o status de {user}", "A valid username must be provided" : "Forneça um nome de usuário válido", "Error creating user: {message}" : "Erro criando o usuário: {message}", @@ -211,13 +212,13 @@ "NT LAN Manager" : "Gerenciador NT LAN", "SSL/TLS" : "SSL/TLS", "STARTTLS" : "STARTTLS", - "Email server" : "Servidor de e-mail", + "Email server" : "Servidor de email", "Open documentation" : "Abrir documentação", - "It is important to set up this server to be able to send emails, like for password reset and notifications." : "É importante configurar este servidor para poder enviar e-mails, assim como para redefinir a senha e notificações.", + "It is important to set up this server to be able to send emails, like for password reset and notifications." : "É importante configurar este servidor para poder enviar emails para redefinir a senha e notificações.", "Send mode" : "Modo de envio", "Encryption" : "Criptografia", "From address" : "Endereço \"From\"", - "mail" : "e-mail", + "mail" : "email", "Authentication method" : "Método de autenticação", "Authentication required" : "Autenticação é requerida", "Server address" : "Endereço do servidor", @@ -226,10 +227,10 @@ "SMTP Username" : "Nome do Usuário SMTP", "SMTP Password" : "Senha SMTP", "Store credentials" : "Armazenar credenciais", - "Test email settings" : "Configurações do e-mail de teste", - "Send email" : "Enviar e-mail", + "Test email settings" : "Configurações do email de teste", + "Send email" : "Enviar email", "Server-side encryption" : "Criptografia do lado do servidor", - "Server-side encryption makes it possible to encrypt files which are uploaded to this server. This comes with limitations like a performance penalty, so enable this only if needed." : "A criptografia do lado do servidor torna possível criptografar arquivos que são carregados para este servidor. Isso diminui um pouco o desempenho, portanto habilite apenas se necessário.", + "Server-side encryption makes it possible to encrypt files which are uploaded to this server. This comes with limitations like a performance penalty, so enable this only if needed." : "A criptografia do lado do servidor torna possível criptografar arquivos que são carregados para este servidor. Isso diminui um pouco o desempenho portanto habilite apenas se necessário.", "Enable server-side encryption" : "Habilitar a criptografia do lado do servidor", "Please read carefully before activating server-side encryption: " : "Por favor, leia com atenção antes de ativar a criptografia do lado do servidor:", "Once encryption is enabled, all files uploaded to the server from that point forward will be encrypted at rest on the server. It will only be possible to disable encryption at a later date if the active encryption module supports that function, and all pre-conditions (e.g. setting a recover key) are met." : "Uma vez que a criptografia é ativada, todos os arquivos enviados ao servidor a partir desse ponto em diante serão criptografados e assim ficarão no servidor. Só será possível desativar a criptografia em uma data posterior se o módulo de criptografia ativo suportar essa função e todas as pré-condições sejam cumpridas (ex., defininindo uma chave de recuperação).", @@ -293,7 +294,7 @@ "This text will be shown on the public link upload page when the file list is hidden." : "Este texto será mostrado na página de envio do link público quando a lista de arquivos está oculta.", "Default share permissions" : "Permissões padrão de compartilhamento", "Tips & tricks" : "Dicas & Truques", - "There are a lot of features and config switches available to optimally customize and use this instance. Here are some pointers for more information." : "Há muitos recursos e opções de configuração para otimização e uso. Aqui estão algumas indicações para obter mais informações.", + "There are a lot of features and config switches available to optimally customize and use this instance. Here are some pointers for more information." : "Há muitos recursos e opções de configuração para otimização e uso. Aqui estão algumas indicações para obter mais informações:", "SQLite is currently being used as the backend database. For larger installations we recommend that you switch to a different database backend." : "SQLite é usando atualmente como Plataforma de serviço de banco de dados. Para instalações maiores recomendamos que você use uma outra plataforma de serviço de banco de dados", "This is particularly recommended when using the desktop client for file synchronisation." : "Isso é particulamente recomendado quando se utiliza um cliente para sincronização.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation ↗</a>." : "Para migrar a outro banco de dados, use a ferramenta de linha de comando: 'occ db:convert-type', ou leia na <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentação ↗</a> como fazer isso.", @@ -318,9 +319,9 @@ "You are member of the following groups:" : "Você é membro dos seguintes grupos:", "Full name" : "Nome completo", "No display name set" : "Nenhum nome de exibição definido", - "Email" : "E-mail", - "Your email address" : "Seu endereço de e-mail", - "No email address set" : "Nenhum endereço de e-mail foi configurado", + "Email" : "Email", + "Your email address" : "Seu endereço de email", + "No email address set" : "Nenhum endereço de email foi configurado", "For password reset and notifications" : "Para redefinição de senha e notificações", "Phone number" : "Número de telefone", "Your phone number" : "Seu número de telefone", @@ -341,7 +342,7 @@ "Device" : "Dispositivo", "Last activity" : "Última atividade", "App name" : "Nome do aplicativo", - "Create new app password" : "Criar uma nova senha do aplicativo", + "Create new app password" : "Criar nova senha de aplicativo", "Use the credentials below to configure your app or device." : "Use as credenciais abaixo para configurar seu aplicativo ou dispositivo.", "For security reasons this password will only be shown once." : "Por motivo de segurança, esta senha só será exibida uma vez.", "Username" : "Nome de Usuário", @@ -356,7 +357,7 @@ "Show storage location" : "Mostrar localização do armazenamento", "Show user backend" : "Mostrar plataforma de serviço de usuário", "Show last login" : "Mostrar último login", - "When the password of a new user is left empty, an activation email with a link to set the password is sent." : "Quando a senha de um novo usuário é deixada em branco, um e-mail de ativação com um link para definir a senha é enviado.", + "When the password of a new user is left empty, an activation email with a link to set the password is sent." : "Quando a senha de um novo usuário é deixada em branco, um email de ativação com um link para definir a senha é enviado.", "Add user" : "Adicionar usuário", "Everyone" : "Para todos", "Admins" : "Administradores", @@ -371,12 +372,12 @@ "Storage location" : "Local do armazenamento", "User backend" : "Plataforma de serviço de usuário", "Last login" : "Último acesso", - "E-Mail" : "E-mail", + "E-Mail" : "Email", "Admin Recovery Password" : "Senha de recuperação do administrador", "Enter the recovery password in order to recover the users files during password change" : "Digite a senha de recuperação para recuperar os arquivos dos usuários durante a mudança de senha.", "change full name" : "alterar nome completo", "set new password" : "definir uma senha nova", - "change email address" : "Alterar o endereço de e-mail", + "change email address" : "Alterar o endereço de email", "Default" : "Padrão", "A problem occurred, please check your log files (Error: %s)" : "Ocorreu um problema, por favor verifique seus arquivos de log (Erro: %s)", "Migration Completed" : "Migração concluída", @@ -387,7 +388,7 @@ "Error while updating app" : "Erro ao atualizar aplicativo", "Error while removing app" : "Erro ao excluir aplicativo", "A valid password must be provided" : "Forneça uma senha válida", - "A valid email must be provided" : "Um e-mail válido deve ser fornecido", + "A valid email must be provided" : "Um email válido deve ser fornecido", "__language_name__" : "Português Brasileiro", "Verifying" : "Verificando", "Personal info" : "Informação pessoal", @@ -421,8 +422,8 @@ "Follow us on Twitter!" : "Siga-nos no Twitter!", "Check out our blog!" : "Confira nosso blog!", "Subscribe to our newsletter!" : "Assine nosso boletim de notícias!", - "Show email address" : "Mostrar o endereço de e-mail", - "Send email to new user" : "Enviar um e-mail para o novo usuário", + "Show email address" : "Mostrar o endereço de email", + "Send email to new user" : "Enviar um email para o novo usuário", "Create" : "Criar", "Group name" : "Nome do grupo" },"pluralForm" :"nplurals=2; plural=(n > 1);" diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js index 6ebb6e5bea6..3772a837c1d 100644 --- a/settings/l10n/ru.js +++ b/settings/l10n/ru.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Хороший пароль", "Strong password" : "Надёжный пароль", "Groups" : "Группы", + "Group list is empty" : "Список групп пуст", "Unable to retrieve the group list" : "Не удается получить список групп", "Unable to delete {objName}" : "Невозможно удалить {objName}", "Error creating group: {message}" : "Ошибка создания группы: {message}", diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json index 81de625a37b..339f000fd3e 100644 --- a/settings/l10n/ru.json +++ b/settings/l10n/ru.json @@ -156,6 +156,7 @@ "Good password" : "Хороший пароль", "Strong password" : "Надёжный пароль", "Groups" : "Группы", + "Group list is empty" : "Список групп пуст", "Unable to retrieve the group list" : "Не удается получить список групп", "Unable to delete {objName}" : "Невозможно удалить {objName}", "Error creating group: {message}" : "Ошибка создания группы: {message}", diff --git a/settings/l10n/sr.js b/settings/l10n/sr.js index 590f2ed4a12..8661adbd52b 100644 --- a/settings/l10n/sr.js +++ b/settings/l10n/sr.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Добра лозинка", "Strong password" : "Јака лозинка", "Groups" : "Групе", + "Group list is empty" : "Списак група је празан", "Unable to retrieve the group list" : "Није могуће дохватити списак група", "Unable to delete {objName}" : "Не могу да обришем {objName}", "Error creating group: {message}" : "Грешка при прављењу групе: {message}", diff --git a/settings/l10n/sr.json b/settings/l10n/sr.json index fd7a6bbc1d8..04064dfdf1b 100644 --- a/settings/l10n/sr.json +++ b/settings/l10n/sr.json @@ -156,6 +156,7 @@ "Good password" : "Добра лозинка", "Strong password" : "Јака лозинка", "Groups" : "Групе", + "Group list is empty" : "Списак група је празан", "Unable to retrieve the group list" : "Није могуће дохватити списак група", "Unable to delete {objName}" : "Не могу да обришем {objName}", "Error creating group: {message}" : "Грешка при прављењу групе: {message}", diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js index 712d9e0df36..2dd43bed6a2 100644 --- a/settings/l10n/tr.js +++ b/settings/l10n/tr.js @@ -158,6 +158,7 @@ OC.L10N.register( "Good password" : "Parola iyi", "Strong password" : "Parola güçlü", "Groups" : "Gruplar", + "Group list is empty" : "Grup listesi boş", "Unable to retrieve the group list" : "Grup listesi alınamadı", "Unable to delete {objName}" : "{objName} silinemedi", "Error creating group: {message}" : "Grup oluşturulurken sorun çıktı: {message}", diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json index 4a358b65c96..408578176a7 100644 --- a/settings/l10n/tr.json +++ b/settings/l10n/tr.json @@ -156,6 +156,7 @@ "Good password" : "Parola iyi", "Strong password" : "Parola güçlü", "Groups" : "Gruplar", + "Group list is empty" : "Grup listesi boş", "Unable to retrieve the group list" : "Grup listesi alınamadı", "Unable to delete {objName}" : "{objName} silinemedi", "Error creating group: {message}" : "Grup oluşturulurken sorun çıktı: {message}", diff --git a/settings/tests/js/users/deleteHandlerSpec.js b/settings/tests/js/users/deleteHandlerSpec.js index 3e7f768e519..98530c47eed 100644 --- a/settings/tests/js/users/deleteHandlerSpec.js +++ b/settings/tests/js/users/deleteHandlerSpec.js @@ -79,7 +79,7 @@ describe('DeleteHandler tests', function() { expect(showNotificationSpy.calledOnce).toEqual(true); expect(showNotificationSpy.getCall(0).args[0]).toEqual('removed some_uid entry'); - showNotificationSpy.reset(); + showNotificationSpy.resetHistory(); handler.mark('some_other_uid'); |