diff options
author | Tomasz Grobelny <tomasz@grobelny.net> | 2018-11-03 23:55:06 +0000 |
---|---|---|
committer | Tomasz Grobelny <tomasz@grobelny.net> | 2018-11-04 09:39:19 +0000 |
commit | 1fa6e0be23f0684ce76de3311c52e01495a4de7e (patch) | |
tree | ef50b564c793d77ef5ade04349f6c5f97a22c7f5 | |
parent | 41687ef00fa5667467564770a4e29403e32d167f (diff) | |
parent | b9783993da7c689b0b1e55dc5696b0c3f90a4c10 (diff) | |
download | nextcloud-server-1fa6e0be23f0684ce76de3311c52e01495a4de7e.tar.gz nextcloud-server-1fa6e0be23f0684ce76de3311c52e01495a4de7e.zip |
Merge remote-tracking branch 'upstream/master' into fix_file_move
Signed-off-by: Tomasz Grobelny <tomasz@grobelny.net>
361 files changed, 11033 insertions, 3337 deletions
diff --git a/3rdparty b/3rdparty -Subproject 8633304ce214a7c0ff8e4fd72052a5ed7a444b6 +Subproject 214c4155f587f5178d792fe4a839044bdc9982f diff --git a/README.md b/README.md index 313c1bf84db..37fbe567100 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Nextcloud Server +# Nextcloud Server ☁ [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nextcloud/server/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/nextcloud/server/?branch=master) [![codecov](https://codecov.io/gh/nextcloud/server/branch/master/graph/badge.svg)](https://codecov.io/gh/nextcloud/server) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/209/badge)](https://bestpractices.coreinfrastructure.org/projects/209) @@ -7,45 +7,102 @@ **A safe home for all your data.** -![](https://github.com/nextcloud/screenshots/blob/master/files/filelist.png) +![](https://raw.githubusercontent.com/nextcloud/screenshots/master/files/Files%20Sharing.png) -## Why is this so awesome? +## Why is this so awesome? 🤩 -* :file_folder: **Access your Data** You can store your files, contacts, calendars and more on a server of your choosing. -* :package: **Sync your Data** You keep your files, contacts, calendars and more synchronized amongst your devices. -* :arrows_counterclockwise: **Share your Data** …by giving others access to the stuff you want them to see or to collaborate with. -* :rocket: **Expandable with dozens of Apps** ...like [Calendar](https://github.com/nextcloud/calendar), [Contacts](https://github.com/nextcloud/contacts), [Mail](https://github.com/nextcloud/mail) and all those you can discover in our [App Store](https://apps.nextcloud.com) -* :lock: **Security** with our encryption mechanisms, [HackerOne bounty program](https://hackerone.com/nextcloud) and two-factor authentication. +* 📁 **Access your Data** You can store your files, contacts, calendars and more on a server of your choosing. +* 🔄 **Sync your Data** You keep your files, contacts, calendars and more synchronized amongst your devices. +* 🙌 **Share your Data** …by giving others access to the stuff you want them to see or to collaborate with. +* 🚀 **Expandable with dozens of Apps** ...like [Calendar](https://github.com/nextcloud/calendar), [Contacts](https://github.com/nextcloud/contacts), [Mail](https://github.com/nextcloud/mail) and all those you can discover in our [App Store](https://apps.nextcloud.com) +* 🔒 **Security** with our encryption mechanisms, [HackerOne bounty program](https://hackerone.com/nextcloud) and two-factor authentication. -*You want to learn more about how you can use Nextcloud to access, share and protect your files, calendars, contacts, communication & more at home and at your Enterprise?* [**Learn about all our Features**](https://nextcloud.com/features). +You want to learn more about how you can use Nextcloud to access, share and protect your files, calendars, contacts, communication & more at home and at your Enterprise? [**Learn about all our Features**](https://nextcloud.com/features). -## Get your Nextcloud +## Get your Nextcloud 🚚 -- [**Install** a server by yourself on your own hardware or by using one of our ready to use **Appliances**](https://nextcloud.com/install/#instructions-server) -- [Buy one of the awesome **devices** coming with a preinstalled Nextcloud](https://nextcloud.com/devices/) -- [Find a service **provider** who is hosting Nextcloud for you or your company](https://nextcloud.com/providers/) +- ☑️ [**Simply sign up**](https://nextcloud.com/signup/) either through our website or through the apps directly. +- 🖥 [**Install** a server by yourself](https://nextcloud.com/install/#instructions-server) on your own hardware or by using one of our ready to use **appliances** +- 📦 Buy one of the [awesome **devices** coming with a preinstalled Nextcloud](https://nextcloud.com/devices/) +- 🏢 Find a [service **provider**](https://nextcloud.com/providers/) who hosts Nextcloud for you or your company -*Enterprise? Public Sector or Education user? You may want to have a look into the [**Enterprise Support Subscription**](https://nextcloud.com/enterprise/) provided by the Nextcloud GmbH* +Enterprise? Public Sector or Education user? You may want to have a look into the [**Enterprise Support Subscription**](https://nextcloud.com/enterprise/) provided by the Nextcloud GmbH. -## Get in touch +## Get in touch 💬 -* :clipboard: [Forum](https://help.nextcloud.com) -* :busts_in_silhouette: [Facebook](https://facebook.com/nextclouders) -* :hatching_chick: [Twitter](https://twitter.com/Nextclouders) -* :elephant: [Mastodon](https://mastodon.xyz/@nextcloud) +* [📋 Forum](https://help.nextcloud.com) +* [👥 Facebook](https://facebook.com/nextclouders) +* [🐣 Twitter](https://twitter.com/Nextclouders) +* [🐘 Mastodon](https://mastodon.xyz/@nextcloud) -[…learn more about how to get support for Nextcloud here!](https://nextcloud.com/support) +You can also [get support for Nextcloud](https://nextcloud.com/support)! -## Join the team :family: -### How to contribute +## Join the team 👪 -1. [Set up your local development environment](https://docs.nextcloud.com/server/14/developer_manual/general/devenv.html) :rocket: -2. [Pick a good first issue](https://github.com/nextcloud/server/labels/good%20first%20issue) :notebook: -3. Create a branch, a [Pull Request](https://opensource.guide/how-to-contribute/#opening-a-pull-request) and `@mention` the people from the issue :computer: -4. Wait for it to get merged and :tada: +There are many ways to contribute, of which development is only one! Find out [how to get involved](https://nextcloud.com/contribute/), including as translator, designer, tester, helping others and much more! 😍 -### Contribution Guidelines + +### Development setup 👩💻 + +1. 🚀 [Set up your local development environment](https://docs.nextcloud.com/server/14/developer_manual/general/devenv.html) +2. 🐛 [Pick a good first issue](https://github.com/nextcloud/server/labels/good%20first%20issue) +3. 👩🔧 Create a branch and make your changes. Remember to sign off your commits using `git commit -sm "Your commit message"` +4. ⬆ Create a [pull request](https://opensource.guide/how-to-contribute/#opening-a-pull-request) and `@mention` the people from the issue to review +5. 👍 Fix things that come up during review +6. 🎉 Wait for it to get merged! + +Third-party components are handled as git submodules which have to be initialized first. So aside from the regular git checkout invoking `git submodule update --init` or a similar command is needed, for details see Git documentation. + +Several apps that are included by default in regular releases such as [First run wizard](https://github.com/nextcloud/firstrunwizard) or [Activity](https://github.com/nextcloud/activity) are missing in `master` and have to be installed manually by cloning them into the `apps` subfolder. + +Otherwise, git checkouts can be handled the same as release archives, by using the `stable*` branches. Note they should never be used on production systems. + + +### Building front-end code 🏗 + +We move more and more towards using Vue.js in the frontend, starting with Settings. For building the code on changes, use these terminal commands in the `settings` subfolder: + +``` bash +# install dependencies +make dev-setup + +# build for development +make build-js + +# build for development and watch edits +make watch-js + +# build for production with minification +make build-js-production + +# clean output files +make clean +``` + +**When making changes, also commit the compiled files!** + +We still use Handlebars templates some places in Files and Settings. We will replace these step-by-step with Vue.js, but in the meantime you need to compile them separately. + +If you don’t have Handlebars installed yet, you can do it with this terminal command: +``` +sudo npm install -g handlebars +``` + +Then inside the root folder of your local Nextcloud development installation, run this command in the terminal every time you changed a `.handlebars` file to compile it: +``` +./build/compile-handlebars-templates.sh +``` + + +### Tools we use 🛠 + +- [👀 BrowserStack](https://browserstack.com) for cross-browser testing +- [🌊 WAVE](https://wave.webaim.org/extension/) for accessibility testing +- [🚨 Lighthouse](https://developers.google.com/web/tools/lighthouse/) for testing of performance, accessibility and more + + +## Contribution guidelines 📜 All contributions to this repository from June, 16 2016 on are considered to be licensed under the AGPLv3 or any later version. @@ -64,17 +121,3 @@ Please read the [Code of Conduct](https://nextcloud.com/community/code-of-conduc Please review the [guidelines for contributing](.github/CONTRIBUTING.md) to this repository. More information how to contribute: [https://nextcloud.com/contribute/](https://nextcloud.com/contribute/) - -### Running master checkouts - -Third-party components are handled as git submodules which have to be initialized first. So aside from the regular git checkout invoking `git submodule update --init` or a similar command is needed, for details see Git documentation. - -Several apps that are included by default in regular releases such as [firstrunwizard](https://github.com/nextcloud/firstrunwizard) or [gallery](https://github.com/nextcloud/gallery) are missing in `master` and have to be installed manually. - -That aside Git checkouts can be handled the same as release archives. - -Note they should never be used on production systems. - -## Tools we use - -[![BrowserStack](https://user-images.githubusercontent.com/45821/41675934-61fa3442-74c4-11e8-8c8e-90768c56ba08.png)](https://www.browserstack.com/) diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index fe7557f7e08..c9680651ff9 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -156,6 +156,7 @@ return array( 'OCA\\DAV\\Migration\\Version1005Date20180530124431' => $baseDir . '/../lib/Migration/Version1005Date20180530124431.php', 'OCA\\DAV\\Migration\\Version1006Date20180619154313' => $baseDir . '/../lib/Migration/Version1006Date20180619154313.php', 'OCA\\DAV\\Migration\\Version1007Date20181007225117' => $baseDir . '/../lib/Migration/Version1007Date20181007225117.php', + 'OCA\\DAV\\Migration\\Version1008Date20181030113700' => $baseDir . '/../lib/Migration/Version1008Date20181030113700.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 1668f1270f5..71879abc0a5 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -171,6 +171,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Migration\\Version1005Date20180530124431' => __DIR__ . '/..' . '/../lib/Migration/Version1005Date20180530124431.php', 'OCA\\DAV\\Migration\\Version1006Date20180619154313' => __DIR__ . '/..' . '/../lib/Migration/Version1006Date20180619154313.php', 'OCA\\DAV\\Migration\\Version1007Date20181007225117' => __DIR__ . '/..' . '/../lib/Migration/Version1007Date20181007225117.php', + 'OCA\\DAV\\Migration\\Version1008Date20181030113700' => __DIR__ . '/..' . '/../lib/Migration/Version1008Date20181030113700.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/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 6f303acba33..3ff3ed0c569 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -170,7 +170,7 @@ class IMipPlugin extends SabreIMipPlugin { $vevent = $iTipMessage->message->VEVENT; $attendee = $this->getCurrentAttendee($iTipMessage); - $defaultLang = $this->config->getUserValue($this->userId, 'core', 'lang', $this->l10nFactory->findLanguage()); + $defaultLang = $this->l10nFactory->findLanguage(); $lang = $this->getAttendeeLangOrDefault($defaultLang, $attendee); $l10n = $this->l10nFactory->get('dav', $lang); diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php index 5034b16ed2f..1aedd5d5643 100644 --- a/apps/dav/lib/CardDAV/AddressBookImpl.php +++ b/apps/dav/lib/CardDAV/AddressBookImpl.php @@ -88,16 +88,26 @@ class AddressBookImpl implements IAddressBook { /** * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match - * @param array $options - for future use. One should always have options! + * @param array $options Options to define the output format + * - types boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array + * example: ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['type => 'HOME', 'value' => 'g@h.i']] + * @return array an array of contacts which are arrays of key-value-pairs + * example result: + * [ + * ['id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'], + * ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['d@e.f', 'g@h.i']] + * ] * @return array an array of contacts which are arrays of key-value-pairs * @since 5.0.0 */ public function search($pattern, $searchProperties, $options) { $results = $this->backend->search($this->getKey(), $pattern, $searchProperties); + $withTypes = \array_key_exists('types', $options) && $options['types'] === true; + $vCards = []; foreach ($results as $result) { - $vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata'])); + $vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata']), $withTypes); } return $vCards; @@ -220,7 +230,7 @@ class AddressBookImpl implements IAddressBook { * @param VCard $vCard * @return array */ - protected function vCard2Array($uri, VCard $vCard) { + protected function vCard2Array($uri, VCard $vCard, $withTypes = false) { $result = [ 'URI' => $uri, ]; @@ -255,15 +265,28 @@ class AddressBookImpl implements IAddressBook { $result[$property->name] = []; } - $result[$property->name][] = $property->getValue(); + $type = $this->getTypeFromProperty($property); + if ($withTypes) { + $result[$property->name][] = [ + 'type' => $type, + 'value' => $property->getValue() + ]; + } else { + $result[$property->name][] = $property->getValue(); + } + } else { $result[$property->name] = $property->getValue(); } } - if ($this->addressBookInfo['principaluri'] === 'principals/system/system' && - $this->addressBookInfo['uri'] === 'system') { + if ( + $this->addressBookInfo['principaluri'] === 'principals/system/system' && ( + $this->addressBookInfo['uri'] === 'system' || + $this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl() + ) + ) { $result['isLocalSystemBook'] = true; } return $result; diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index a2d3b03147b..a8907f631cd 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -494,7 +494,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { */ function getCards($addressBookId) { $query = $this->db->getQueryBuilder(); - $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata']) + $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata', 'uid']) ->from('cards') ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); @@ -525,7 +525,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { */ function getCard($addressBookId, $cardUri) { $query = $this->db->getQueryBuilder(); - $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata']) + $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata', 'uid']) ->from('cards') ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($cardUri))) @@ -563,7 +563,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { $cards = []; $query = $this->db->getQueryBuilder(); - $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata']) + $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata', 'uid']) ->from('cards') ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) ->andWhere($query->expr()->in('uri', $query->createParameter('uri'))); @@ -609,6 +609,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { */ function createCard($addressBookId, $cardUri, $cardData) { $etag = md5($cardData); + $uid = $this->getUID($cardData); $query = $this->db->getQueryBuilder(); $query->insert('cards') @@ -619,6 +620,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { 'addressbookid' => $query->createNamedParameter($addressBookId), 'size' => $query->createNamedParameter(strlen($cardData)), 'etag' => $query->createNamedParameter($etag), + 'uid' => $query->createNamedParameter($uid), ]) ->execute(); @@ -661,6 +663,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { */ function updateCard($addressBookId, $cardUri, $cardData) { + $uid = $this->getUID($cardData); $etag = md5($cardData); $query = $this->db->getQueryBuilder(); $query->update('cards') @@ -668,6 +671,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { ->set('lastmodified', $query->createNamedParameter(time())) ->set('size', $query->createNamedParameter(strlen($cardData))) ->set('etag', $query->createNamedParameter($etag)) + ->set('uid', $query->createNamedParameter($uid)) ->where($query->expr()->eq('uri', $query->createNamedParameter($cardUri))) ->andWhere($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) ->execute(); @@ -1125,4 +1129,25 @@ class CardDavBackend implements BackendInterface, SyncSupport { $addressbookInfo[$displaynameKey] = $principalInformation['{DAV:}displayname']; } } + + /** + * Extract UID from vcard + * + * @param string $cardData the vcard raw data + * @return string the uid + * @throws BadRequest if no UID is available + */ + private function getUID($cardData) { + if ($cardData != '') { + $vCard = Reader::read($cardData); + if ($vCard->UID) { + $uid = $vCard->UID->getValue(); + return $uid; + } + // should already be handled, but just in case + throw new BadRequest('vCards on CardDAV servers MUST have a UID property'); + } + // should already be handled, but just in case + throw new BadRequest('vCard can not be empty'); + } } diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php index fcd1b34edbc..292be61c9dc 100644 --- a/apps/dav/lib/Connector/Sabre/Auth.php +++ b/apps/dav/lib/Connector/Sabre/Auth.php @@ -228,11 +228,12 @@ class Auth extends AbstractBasic { if($this->twoFactorManager->needsSecondFactor($this->userSession->getUser())) { throw new \Sabre\DAV\Exception\NotAuthenticated('2FA challenge not passed.'); } - if (\OC_User::handleApacheAuth() || + if ( //Fix for broken webdav clients ($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED))) || //Well behaved clients that only send the cookie are allowed - ($this->userSession->isLoggedIn() && $this->session->get(self::DAV_AUTHENTICATED) === $this->userSession->getUser()->getUID() && $request->getHeader('Authorization') === null) + ($this->userSession->isLoggedIn() && $this->session->get(self::DAV_AUTHENTICATED) === $this->userSession->getUser()->getUID() && $request->getHeader('Authorization') === null) || + \OC_User::handleApacheAuth() ) { $user = $this->userSession->getUser()->getUID(); \OC_Util::setupFS($user); diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php index 9e927ff85e5..57c072fda47 100644 --- a/apps/dav/lib/Connector/Sabre/File.php +++ b/apps/dav/lib/Connector/Sabre/File.php @@ -164,14 +164,19 @@ class File extends Node implements IFile { $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE); } - $target = $partStorage->fopen($internalPartPath, 'wb'); - if ($target === false) { - \OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']); - // because we have no clue about the cause we can only throw back a 500/Internal Server Error - throw new Exception('Could not write file contents'); + if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) { + $count = $partStorage->writeStream($internalPartPath, $data); + $result = $count > 0; + } else { + $target = $partStorage->fopen($internalPartPath, 'wb'); + if ($target === false) { + \OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']); + // because we have no clue about the cause we can only throw back a 500/Internal Server Error + throw new Exception('Could not write file contents'); + } + list($count, $result) = \OC_Helper::streamCopy($data, $target); + fclose($target); } - list($count, $result) = \OC_Helper::streamCopy($data, $target); - fclose($target); if ($result === false) { $expected = -1; @@ -185,7 +190,7 @@ class File extends Node implements IFile { // double check if the file was fully received // compare expected and actual size if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') { - $expected = (int) $_SERVER['CONTENT_LENGTH']; + $expected = (int)$_SERVER['CONTENT_LENGTH']; if ($count !== $expected) { throw new BadRequest('expected filesize ' . $expected . ' got ' . $count); } @@ -219,7 +224,7 @@ class File extends Node implements IFile { $renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath); $fileExists = $storage->file_exists($internalPath); if ($renameOkay === false || $fileExists === false) { - \OC::$server->getLogger()->error('renaming part file to final file failed ($run: ' . ( $run ? 'true' : 'false' ) . ', $renameOkay: ' . ( $renameOkay ? 'true' : 'false' ) . ', $fileExists: ' . ( $fileExists ? 'true' : 'false' ) . ')', ['app' => 'webdav']); + \OC::$server->getLogger()->error('renaming part file to final file failed $renameOkay: ' . ($renameOkay ? 'true' : 'false') . ', $fileExists: ' . ($fileExists ? 'true' : 'false') . ')', ['app' => 'webdav']); throw new Exception('Could not rename part file to final file'); } } catch (ForbiddenException $ex) { @@ -246,7 +251,7 @@ class File extends Node implements IFile { $this->header('X-OC-MTime: accepted'); } } - + if ($view) { $this->emitPostHooks($exists); } @@ -443,7 +448,7 @@ class File extends Node implements IFile { //detect aborted upload if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') { if (isset($_SERVER['CONTENT_LENGTH'])) { - $expected = (int) $_SERVER['CONTENT_LENGTH']; + $expected = (int)$_SERVER['CONTENT_LENGTH']; if ($bytesWritten !== $expected) { $chunk_handler->remove($info['index']); throw new BadRequest( diff --git a/apps/dav/lib/Migration/Version1008Date20181030113700.php b/apps/dav/lib/Migration/Version1008Date20181030113700.php new file mode 100644 index 00000000000..1cc6223a9e9 --- /dev/null +++ b/apps/dav/lib/Migration/Version1008Date20181030113700.php @@ -0,0 +1,52 @@ +<?php +/** + * @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com) + * + * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> + * + * @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 Closure; + +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +/** + * add column for share notes + * + * Class Version15000Date20180927120000 + */ +class Version1008Date20181030113700 extends SimpleMigrationStep { + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { + + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('cards'); + $table->addColumn('uid', Type::STRING, [ + 'notnull' => false, + 'length' => 255 + ]); + + return $schema; + } +} diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php index 739b81ddf01..651fbf5eaf8 100644 --- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php +++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php @@ -231,9 +231,9 @@ class BirthdayServiceTest extends TestCase { if ($expectedOp === 'create') { $service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn(new VCalendar()); $this->calDav->expects($this->exactly(3))->method('createCalendarObject')->withConsecutive( - [1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.2//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], - [1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.2//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], - [1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.2//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"] + [1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.6//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.6//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.6//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"] ); } if ($expectedOp === 'update') { @@ -241,9 +241,9 @@ class BirthdayServiceTest extends TestCase { $service->expects($this->exactly(3))->method('birthdayEvenChanged')->willReturn(true); $this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn(['calendardata' => '']); $this->calDav->expects($this->exactly(3))->method('updateCalendarObject')->withConsecutive( - [1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.2//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], - [1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.2//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], - [1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.2//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"] + [1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.6//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.6//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"], + [1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.6//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"] ); } diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index 816ba670990..2f5287df82c 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -87,6 +87,14 @@ class CardDavBackendTest extends TestCase { const UNIT_TEST_USER1 = 'principals/users/carddav-unit-test1'; const UNIT_TEST_GROUP = 'principals/groups/carddav-unit-test-group'; + private $vcardTest = 'BEGIN:VCARD'.PHP_EOL. + 'VERSION:3.0'.PHP_EOL. + 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL. + 'UID:Test'.PHP_EOL. + 'FN:Test'.PHP_EOL. + 'N:Test;;;;'.PHP_EOL. + 'END:VCARD'; + public function setUp() { parent::setUp(); @@ -121,7 +129,6 @@ class CardDavBackendTest extends TestCase { $query = $this->db->getQueryBuilder(); $query->delete('cards')->execute(); - $this->tearDown(); } @@ -217,8 +224,8 @@ class CardDavBackendTest extends TestCase { $uri = $this->getUniqueID('card'); // updateProperties is expected twice, once for createCard and once for updateCard - $backend->expects($this->at(0))->method('updateProperties')->with($bookId, $uri, ''); - $backend->expects($this->at(1))->method('updateProperties')->with($bookId, $uri, '***'); + $backend->expects($this->at(0))->method('updateProperties')->with($bookId, $uri, $this->vcardTest); + $backend->expects($this->at(1))->method('updateProperties')->with($bookId, $uri, $this->vcardTest); // Expect event $this->dispatcher->expects($this->at(0)) @@ -226,16 +233,16 @@ class CardDavBackendTest extends TestCase { ->with('\OCA\DAV\CardDAV\CardDavBackend::createCard', $this->callback(function(GenericEvent $e) use ($bookId, $uri) { return $e->getArgument('addressBookId') === $bookId && $e->getArgument('cardUri') === $uri && - $e->getArgument('cardData') === ''; + $e->getArgument('cardData') === $this->vcardTest; })); // create a card - $backend->createCard($bookId, $uri, ''); + $backend->createCard($bookId, $uri, $this->vcardTest); // get all the cards $cards = $backend->getCards($bookId); $this->assertEquals(1, count($cards)); - $this->assertEquals('', $cards[0]['carddata']); + $this->assertEquals($this->vcardTest, $cards[0]['carddata']); // get the cards $card = $backend->getCard($bookId, $uri); @@ -245,7 +252,7 @@ class CardDavBackendTest extends TestCase { $this->assertArrayHasKey('lastmodified', $card); $this->assertArrayHasKey('etag', $card); $this->assertArrayHasKey('size', $card); - $this->assertEquals('', $card['carddata']); + $this->assertEquals($this->vcardTest, $card['carddata']); // Expect event $this->dispatcher->expects($this->at(0)) @@ -253,13 +260,13 @@ class CardDavBackendTest extends TestCase { ->with('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $this->callback(function(GenericEvent $e) use ($bookId, $uri) { return $e->getArgument('addressBookId') === $bookId && $e->getArgument('cardUri') === $uri && - $e->getArgument('cardData') === '***'; + $e->getArgument('cardData') === $this->vcardTest; })); // update the card - $backend->updateCard($bookId, $uri, '***'); + $backend->updateCard($bookId, $uri, $this->vcardTest); $card = $backend->getCard($bookId, $uri); - $this->assertEquals('***', $card['carddata']); + $this->assertEquals($this->vcardTest, $card['carddata']); // Expect event $this->dispatcher->expects($this->at(0)) @@ -290,18 +297,18 @@ class CardDavBackendTest extends TestCase { // create a card $uri0 = $this->getUniqueID('card'); - $this->backend->createCard($bookId, $uri0, ''); + $this->backend->createCard($bookId, $uri0, $this->vcardTest); $uri1 = $this->getUniqueID('card'); - $this->backend->createCard($bookId, $uri1, ''); + $this->backend->createCard($bookId, $uri1, $this->vcardTest); $uri2 = $this->getUniqueID('card'); - $this->backend->createCard($bookId, $uri2, ''); + $this->backend->createCard($bookId, $uri2, $this->vcardTest); // get all the cards $cards = $this->backend->getCards($bookId); $this->assertEquals(3, count($cards)); - $this->assertEquals('', $cards[0]['carddata']); - $this->assertEquals('', $cards[1]['carddata']); - $this->assertEquals('', $cards[2]['carddata']); + $this->assertEquals($this->vcardTest, $cards[0]['carddata']); + $this->assertEquals($this->vcardTest, $cards[1]['carddata']); + $this->assertEquals($this->vcardTest, $cards[2]['carddata']); // get the cards $cards = $this->backend->getMultipleCards($bookId, [$uri1, $uri2]); @@ -312,7 +319,7 @@ class CardDavBackendTest extends TestCase { $this->assertArrayHasKey('lastmodified', $card); $this->assertArrayHasKey('etag', $card); $this->assertArrayHasKey('size', $card); - $this->assertEquals('', $card['carddata']); + $this->assertEquals($this->vcardTest, $card['carddata']); } // delete the card @@ -357,7 +364,7 @@ class CardDavBackendTest extends TestCase { ->method('purgeProperties'); // create a card - $this->backend->createCard($bookId, $uri, ''); + $this->backend->createCard($bookId, $uri, $this->vcardTest); // delete the card $this->assertTrue($this->backend->deleteCard($bookId, $uri)); @@ -380,7 +387,7 @@ class CardDavBackendTest extends TestCase { // add a change $uri0 = $this->getUniqueID('card'); - $this->backend->createCard($bookId, $uri0, ''); + $this->backend->createCard($bookId, $uri0, $this->vcardTest); // look for changes $changes = $this->backend->getChangesForAddressBook($bookId, $syncToken, 1); @@ -683,7 +690,7 @@ class CardDavBackendTest extends TestCase { } $result = $this->backend->getContact(0, 'uri0'); - $this->assertSame(7, count($result)); + $this->assertSame(8, count($result)); $this->assertSame(0, (int)$result['addressbookid']); $this->assertSame('uri0', $result['uri']); $this->assertSame(5489543, (int)$result['lastmodified']); diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php index 5e7a6374206..edb61edc6ed 100644 --- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php @@ -164,7 +164,7 @@ class FileTest extends \Test\TestCase { public function testSimplePutFails($thrownException, $expectedException, $checkPreviousClass = true) { // setup $storage = $this->getMockBuilder(Local::class) - ->setMethods(['fopen']) + ->setMethods(['writeStream']) ->setConstructorArgs([['datadir' => \OC::$server->getTempManager()->getTemporaryFolder()]]) ->getMock(); \OC\Files\Filesystem::mount($storage, [], $this->user . '/'); @@ -182,11 +182,11 @@ class FileTest extends \Test\TestCase { if ($thrownException !== null) { $storage->expects($this->once()) - ->method('fopen') + ->method('writeStream') ->will($this->throwException($thrownException)); } else { $storage->expects($this->once()) - ->method('fopen') + ->method('writeStream') ->will($this->returnValue(false)); } diff --git a/apps/federatedfilesharing/l10n/pl.js b/apps/federatedfilesharing/l10n/pl.js index a8ce17ef8e9..d60b590dd48 100644 --- a/apps/federatedfilesharing/l10n/pl.js +++ b/apps/federatedfilesharing/l10n/pl.js @@ -17,8 +17,12 @@ OC.L10N.register( "Couldn't establish a federated share." : "Nie udało się ustalić Stowarzyszonego udostępnienia.", "Couldn't establish a federated share, maybe the password was wrong." : "Nie udało się ustalić Stowarzyszonego udostępnienia, może być błędne hasło.", "Federated Share request sent, you will receive an invitation. Check your notifications." : "Wysłano żądanie Udostępniania Stowarzyszonego, otrzymasz zaproszenie. Sprawdzaj swoje powiadomienia.", + "Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Nie można ustanowić stowarzyszonego udziału, wygląda na to, że serwer wybrany do stowarzyszenia jest zbyt stary (Nextcloud <= 9).", + "It is not allowed to send federated group shares from this server." : "Wysyłanie stowarzyszonych udziałów grupowych z tego serwera jest zabronione.", + "Sharing %1$s failed, because this item is already shared with %2$s" : "Udostępnianie %1$snie powiodło się, ponieważ ten element jest już udostępniony jako %2$s", "Not allowed to create a federated share with the same user" : "Nie można tworzyć stowarzyszonego udziału z tym samym użytkownikiem", "File is already shared with %s" : "Plik jest już współdzielony z %s", + "Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate." : "Udostępnianie %1$s nie powiodło się, nie można odnaleźć %2$s, być może serwer jest nieosiągalny lub używa certyfikatu z podpisem własnym.", "Could not find share" : "Nie można znaleźć powiązania", "You received \"%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Otrzymałeś \"%3$s\" w zdalnym udziale z %1$s (w imieniu %2$s)", "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Otrzymałeś {share} w zdalnym udziale z {user} (w imieniu {behalf})", @@ -29,11 +33,15 @@ OC.L10N.register( "Share with me through my #Nextcloud Federated Cloud ID, see %s" : "Podziel się ze mną przez mój ID #Nextcloud Stowarzyszonej Chmury, zobacz %s", "Share with me through my #Nextcloud Federated Cloud ID" : "Podziel się ze mną przez mój ID #Nextcloud Stowarzyszonej Chmury", "Sharing" : "Udostępnianie", + "Federated file sharing" : "Stowarzyszone udziały grupowe", + "Provide federated file sharing across servers" : "Zezwól na stowarzyszone udostępnianie plików na serwerach", "Federated Cloud Sharing" : "Dzielenie się ze Stowarzyszoną Chmurą", "Open documentation" : "Otwórz dokumentację", "Adjust how people can share between servers." : "Dostosuj ustawienia współdzielenia między serwerami.", "Allow users on this server to send shares to other servers" : "Zezwalaj użytkownikom na tym serwerze wysłać udostępnienia do innych serwerów", "Allow users on this server to receive shares from other servers" : "Zezwalaj użytkownikom na tym serwerze do otrzymania udostępnień z innych serwerów", + "Allow users on this server to send shares to groups on other servers" : "Pozwól użytkownikom na tym serwerze na wysyłanie udziałów do grup na innych serwerach", + "Allow users on this server to receive group shares from other servers" : "Pozwól użytkownikom na tym serwerze na odbieranie udziałów grupy z innych serwerów", "Search global and public address book for users" : "Szukaj użytkowników w globalnej i publicznej książce adresowej", "Allow users to publish their data to a global and public address book" : "Pozwól użytkownikom na publikację ich danych do globalnej i publicznej książki adresowej", "Federated Cloud" : "Stowarzyszona Chmura", diff --git a/apps/federatedfilesharing/l10n/pl.json b/apps/federatedfilesharing/l10n/pl.json index b7191f76892..745a1faf504 100644 --- a/apps/federatedfilesharing/l10n/pl.json +++ b/apps/federatedfilesharing/l10n/pl.json @@ -15,8 +15,12 @@ "Couldn't establish a federated share." : "Nie udało się ustalić Stowarzyszonego udostępnienia.", "Couldn't establish a federated share, maybe the password was wrong." : "Nie udało się ustalić Stowarzyszonego udostępnienia, może być błędne hasło.", "Federated Share request sent, you will receive an invitation. Check your notifications." : "Wysłano żądanie Udostępniania Stowarzyszonego, otrzymasz zaproszenie. Sprawdzaj swoje powiadomienia.", + "Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Nie można ustanowić stowarzyszonego udziału, wygląda na to, że serwer wybrany do stowarzyszenia jest zbyt stary (Nextcloud <= 9).", + "It is not allowed to send federated group shares from this server." : "Wysyłanie stowarzyszonych udziałów grupowych z tego serwera jest zabronione.", + "Sharing %1$s failed, because this item is already shared with %2$s" : "Udostępnianie %1$snie powiodło się, ponieważ ten element jest już udostępniony jako %2$s", "Not allowed to create a federated share with the same user" : "Nie można tworzyć stowarzyszonego udziału z tym samym użytkownikiem", "File is already shared with %s" : "Plik jest już współdzielony z %s", + "Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate." : "Udostępnianie %1$s nie powiodło się, nie można odnaleźć %2$s, być może serwer jest nieosiągalny lub używa certyfikatu z podpisem własnym.", "Could not find share" : "Nie można znaleźć powiązania", "You received \"%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Otrzymałeś \"%3$s\" w zdalnym udziale z %1$s (w imieniu %2$s)", "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Otrzymałeś {share} w zdalnym udziale z {user} (w imieniu {behalf})", @@ -27,11 +31,15 @@ "Share with me through my #Nextcloud Federated Cloud ID, see %s" : "Podziel się ze mną przez mój ID #Nextcloud Stowarzyszonej Chmury, zobacz %s", "Share with me through my #Nextcloud Federated Cloud ID" : "Podziel się ze mną przez mój ID #Nextcloud Stowarzyszonej Chmury", "Sharing" : "Udostępnianie", + "Federated file sharing" : "Stowarzyszone udziały grupowe", + "Provide federated file sharing across servers" : "Zezwól na stowarzyszone udostępnianie plików na serwerach", "Federated Cloud Sharing" : "Dzielenie się ze Stowarzyszoną Chmurą", "Open documentation" : "Otwórz dokumentację", "Adjust how people can share between servers." : "Dostosuj ustawienia współdzielenia między serwerami.", "Allow users on this server to send shares to other servers" : "Zezwalaj użytkownikom na tym serwerze wysłać udostępnienia do innych serwerów", "Allow users on this server to receive shares from other servers" : "Zezwalaj użytkownikom na tym serwerze do otrzymania udostępnień z innych serwerów", + "Allow users on this server to send shares to groups on other servers" : "Pozwól użytkownikom na tym serwerze na wysyłanie udziałów do grup na innych serwerach", + "Allow users on this server to receive group shares from other servers" : "Pozwól użytkownikom na tym serwerze na odbieranie udziałów grupy z innych serwerów", "Search global and public address book for users" : "Szukaj użytkowników w globalnej i publicznej książce adresowej", "Allow users to publish their data to a global and public address book" : "Pozwól użytkownikom na publikację ich danych do globalnej i publicznej książki adresowej", "Federated Cloud" : "Stowarzyszona Chmura", diff --git a/apps/files/css/detailsView.scss b/apps/files/css/detailsView.scss index f64a3702850..71062648c97 100644 --- a/apps/files/css/detailsView.scss +++ b/apps/files/css/detailsView.scss @@ -15,7 +15,13 @@ #app-sidebar .mainFileInfoView .permalink { padding: 6px 10px; - vertical-align: text-top; + vertical-align: top; + opacity: .6; + + &:hover, + &:focus { + opacity: 1; + } } #app-sidebar .mainFileInfoView .permalink-field>input { clear: both; @@ -87,7 +93,7 @@ } #app-sidebar .fileName h3 { - width: calc(100% - 36px); /* 36px is the with of the copy link icon */ + width: calc(100% - 42px); /* 36px is the with of the copy link icon, but this breaks so we add some more to be sure */ display: inline-block; padding: 5px 0; margin: -5px 0; diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss index 4e0bc9c0160..d6f9bd6131e 100644 --- a/apps/files/css/files.scss +++ b/apps/files/css/files.scss @@ -8,7 +8,12 @@ } /* FILE MENU */ -.actions { padding:5px; height:32px; display: inline-block; float: left; } +.actions { + padding: 5px; + height: 100%; + display: inline-block; + float: left; +} .actions input, .actions button, .actions .button { margin:0; float:left; } .actions .button a { color: #555; } .actions .button a:hover, @@ -316,6 +321,7 @@ table td.filename .thumbnail { background-size: 32px; margin-left: 9px; margin-top: 9px; + border-radius: var(--border-radius); cursor: pointer; position: absolute; z-index: 4; @@ -658,8 +664,14 @@ table.dragshadow td.size { top: 100%; margin-top: 4px; min-width: 100px; - margin-left: 7px; + margin-left: 22px; /* Align left edge below center of + button … */ + transform: translateX(-50%); /* … then center it below button */ z-index: 1001; + + /* Center triangle */ + &::after { + left: calc(50% - 8px) !important; + } } #filestable .filename .action .icon, diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js index cd602961c0a..bac2a5ebd21 100644 --- a/apps/files/js/detailsview.js +++ b/apps/files/js/detailsview.js @@ -174,6 +174,9 @@ // hide other tabs $tabsContainer.find('.tab').addClass('hidden'); + $tabsContainer.attr('class', 'tabsContainer'); + $tabsContainer.addClass(tabView.getTabsContainerExtraClasses()); + // tab already rendered ? if (!$tabEl.length) { // render tab diff --git a/apps/files/js/detailtabview.js b/apps/files/js/detailtabview.js index a66cedbc15d..1e046f30246 100644 --- a/apps/files/js/detailtabview.js +++ b/apps/files/js/detailtabview.js @@ -41,6 +41,21 @@ }, /** + * Returns the extra CSS classes used by the tabs container when this + * tab is the selected one. + * + * In general you should not extend this method, as tabs should not + * modify the classes of its container; this is reserved as a last + * resort for very specific cases in which there is no other way to get + * the proper style or behaviour. + * + * @return {String} space-separated CSS classes + */ + getTabsContainerExtraClasses: function() { + return ''; + }, + + /** * Returns the tab label * * @return {String} label diff --git a/apps/files/l10n/cs.js b/apps/files/l10n/cs.js index cbd6c72d572..96b93d361e7 100644 --- a/apps/files/l10n/cs.js +++ b/apps/files/l10n/cs.js @@ -142,6 +142,7 @@ OC.L10N.register( "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Použijte tuto adresu pro <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">přístup k vašim souborům přes WebDAV</a>", "Cancel upload" : "Zrušit nahrávání", + "Toggle grid view" : "Přepnout zobrazení mřížky", "No files in here" : "Žádné soubory", "Upload some content or sync with your devices!" : "Nahrajte nějaký obsah nebo synchronizujte se svými přístroji!", "No entries found in this folder" : "V této složce nebylo nic nalezeno", diff --git a/apps/files/l10n/cs.json b/apps/files/l10n/cs.json index a8f82c5c5d7..cb01165503d 100644 --- a/apps/files/l10n/cs.json +++ b/apps/files/l10n/cs.json @@ -140,6 +140,7 @@ "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Použijte tuto adresu pro <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">přístup k vašim souborům přes WebDAV</a>", "Cancel upload" : "Zrušit nahrávání", + "Toggle grid view" : "Přepnout zobrazení mřížky", "No files in here" : "Žádné soubory", "Upload some content or sync with your devices!" : "Nahrajte nějaký obsah nebo synchronizujte se svými přístroji!", "No entries found in this folder" : "V této složce nebylo nic nalezeno", diff --git a/apps/files_external/js/app.js b/apps/files_external/js/app.js index d3f738dcf8a..4406882cd21 100644 --- a/apps/files_external/js/app.js +++ b/apps/files_external/js/app.js @@ -8,16 +8,16 @@ * */ -if (!OCA.External) { +if (!OCA.Files_External) { /** * @namespace */ - OCA.External = {}; + OCA.Files_External = {}; } /** * @namespace */ -OCA.External.App = { +OCA.Files_External.App = { fileList: null, @@ -26,7 +26,7 @@ OCA.External.App = { return this.fileList; } - this.fileList = new OCA.External.FileList( + this.fileList = new OCA.Files_External.FileList( $el, { fileActions: this._createFileActions() @@ -67,10 +67,10 @@ OCA.External.App = { $(document).ready(function() { $('#app-content-extstoragemounts').on('show', function(e) { - OCA.External.App.initList($(e.target)); + OCA.Files_External.App.initList($(e.target)); }); $('#app-content-extstoragemounts').on('hide', function() { - OCA.External.App.removeList(); + OCA.Files_External.App.removeList(); }); /* Status Manager */ @@ -82,27 +82,27 @@ $(document).ready(function() { if (e.dir === '/') { var mount_point = e.previousDir.split('/', 2)[1]; // Every time that we return to / root folder from a mountpoint, mount_point status is rechecked - OCA.External.StatusManager.getMountPointList(function() { - OCA.External.StatusManager.recheckConnectivityForMount([mount_point], true); + OCA.Files_External.StatusManager.getMountPointList(function() { + OCA.Files_External.StatusManager.recheckConnectivityForMount([mount_point], true); }); } }) .on('fileActionsReady', function(e){ if ($.isArray(e.$files)) { - if (OCA.External.StatusManager.mountStatus === null || - OCA.External.StatusManager.mountPointList === null || - _.size(OCA.External.StatusManager.mountStatus) !== _.size(OCA.External.StatusManager.mountPointList)) { + if (OCA.Files_External.StatusManager.mountStatus === null || + OCA.Files_External.StatusManager.mountPointList === null || + _.size(OCA.Files_External.StatusManager.mountStatus) !== _.size(OCA.Files_External.StatusManager.mountPointList)) { // Will be the very first check when the files view will be loaded - OCA.External.StatusManager.launchFullConnectivityCheckOneByOne(); + OCA.Files_External.StatusManager.launchFullConnectivityCheckOneByOne(); } else { // When we change between general files view and external files view - OCA.External.StatusManager.getMountPointList(function(){ + OCA.Files_External.StatusManager.getMountPointList(function(){ var fileNames = []; $.each(e.$files, function(key, value){ fileNames.push(value.attr('data-file')); }); // Recheck if launched but work from cache - OCA.External.StatusManager.recheckConnectivityForMount(fileNames, false); + OCA.Files_External.StatusManager.recheckConnectivityForMount(fileNames, false); }); } } diff --git a/apps/files_external/js/mountsfilelist.js b/apps/files_external/js/mountsfilelist.js index 90b90e38745..034c29c05c2 100644 --- a/apps/files_external/js/mountsfilelist.js +++ b/apps/files_external/js/mountsfilelist.js @@ -10,7 +10,7 @@ (function() { /** - * @class OCA.External.FileList + * @class OCA.Files_External.FileList * @augments OCA.Files.FileList * * @classdesc External storage file list. @@ -27,7 +27,7 @@ }; FileList.prototype = _.extend({}, OCA.Files.FileList.prototype, - /** @lends OCA.External.FileList.prototype */ { + /** @lends OCA.Files_External.FileList.prototype */ { appName: 'External storages', _allowSelection: false, @@ -43,7 +43,7 @@ }, /** - * @param {OCA.External.MountPointInfo} fileData + * @param {OCA.Files_External.MountPointInfo} fileData */ _createRow: function(fileData) { // TODO: hook earlier and render the whole row here @@ -138,12 +138,12 @@ /** * Mount point info attributes. * - * @typedef {Object} OCA.External.MountPointInfo + * @typedef {Object} OCA.Files_External.MountPointInfo * * @property {String} name mount point name * @property {String} scope mount point scope "personal" or "system" * @property {String} backend external storage backend name */ - OCA.External.FileList = FileList; + OCA.Files_External.FileList = FileList; })(); diff --git a/apps/files_external/js/oauth1.js b/apps/files_external/js/oauth1.js index 79248a3e3b2..56e674b213b 100644 --- a/apps/files_external/js/oauth1.js +++ b/apps/files_external/js/oauth1.js @@ -4,7 +4,7 @@ $(document).ready(function() { $tr.find('.configuration input.auth-param').attr('disabled', 'disabled').addClass('disabled-success'); } - OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { + OCA.Files_External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { if (authMechanism === 'oauth1::oauth1') { var config = $tr.find('.configuration'); config.append($(document.createElement('input')) @@ -34,7 +34,7 @@ $(document).ready(function() { $(token).val(result.access_token); $(token_secret).val(result.access_token_secret); $(configured).val('true'); - OCA.External.Settings.mountConfig.saveStorageConfig($tr, function(status) { + OCA.Files_External.Settings.mountConfig.saveStorageConfig($tr, function(status) { if (status) { displayGranted($tr); } @@ -64,7 +64,7 @@ $(document).ready(function() { $(configured).val('false'); $(token).val(result.data.request_token); $(token_secret).val(result.data.request_token_secret); - OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() { + OCA.Files_External.Settings.mountConfig.saveStorageConfig(tr, function() { window.location = result.data.url; }); } else { diff --git a/apps/files_external/js/oauth2.js b/apps/files_external/js/oauth2.js index 13b5162694e..fb7160d6684 100644 --- a/apps/files_external/js/oauth2.js +++ b/apps/files_external/js/oauth2.js @@ -4,7 +4,7 @@ $(document).ready(function() { $tr.find('.configuration input.auth-param').attr('disabled', 'disabled').addClass('disabled-success'); } - OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { + OCA.Files_External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { if (authMechanism === 'oauth2::oauth2') { var config = $tr.find('.configuration'); config.append($(document.createElement('input')) @@ -43,7 +43,7 @@ $(document).ready(function() { if (result && result.status == 'success') { $(token).val(result.data.token); $(configured).val('true'); - OCA.External.Settings.mountConfig.saveStorageConfig($tr, function(status) { + OCA.Files_External.Settings.mountConfig.saveStorageConfig($tr, function(status) { if (status) { displayGranted($tr); } @@ -80,7 +80,7 @@ $(document).ready(function() { if (result && result.status == 'success') { $(configured).val('false'); $(token).val('false'); - OCA.External.Settings.mountConfig.saveStorageConfig(tr, function(status) { + OCA.Files_External.Settings.mountConfig.saveStorageConfig(tr, function(status) { window.location = result.data.url; }); } else { diff --git a/apps/files_external/js/public_key.js b/apps/files_external/js/public_key.js index 6856c7d021f..9b9ca6038c8 100644 --- a/apps/files_external/js/public_key.js +++ b/apps/files_external/js/public_key.js @@ -1,6 +1,6 @@ $(document).ready(function() { - OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { + OCA.Files_External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { if (scheme === 'publickey' && authMechanism === 'publickey::rsa') { var config = $tr.find('.configuration'); if ($(config).find('[name="public_key_generate"]').length === 0) { @@ -53,7 +53,7 @@ $(document).ready(function() { if (result && result.status === 'success') { $(config).find('[data-parameter="public_key"]').val(result.data.public_key).keyup(); $(config).find('[data-parameter="private_key"]').val(result.data.private_key); - OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() { + OCA.Files_External.Settings.mountConfig.saveStorageConfig(tr, function() { // Nothing to do }); } else { diff --git a/apps/files_external/js/rollingqueue.js b/apps/files_external/js/rollingqueue.js index 53e11cb1219..df3797ada89 100644 --- a/apps/files_external/js/rollingqueue.js +++ b/apps/files_external/js/rollingqueue.js @@ -124,14 +124,14 @@ var RollingQueue = function (functionList, queueWindow, callback) { }; }; -if (!OCA.External) { - OCA.External = {}; +if (!OCA.Files_External) { + OCA.Files_External = {}; } -if (!OCA.External.StatusManager) { - OCA.External.StatusManager = {}; +if (!OCA.Files_External.StatusManager) { + OCA.Files_External.StatusManager = {}; } -OCA.External.StatusManager.RollingQueue = RollingQueue; +OCA.Files_External.StatusManager.RollingQueue = RollingQueue; })(); diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 2d495281527..adf3f766202 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -163,7 +163,7 @@ function addSelect2 ($elements, userListLimit) { } /** - * @class OCA.External.Settings.StorageConfig + * @class OCA.Files_External.Settings.StorageConfig * * @classdesc External storage config */ @@ -185,7 +185,7 @@ StorageConfig.Visibility = { DEFAULT: 3 }; /** - * @memberof OCA.External.Settings + * @memberof OCA.Files_External.Settings */ StorageConfig.prototype = { _url: null, @@ -348,8 +348,8 @@ StorageConfig.prototype = { }; /** - * @class OCA.External.Settings.GlobalStorageConfig - * @augments OCA.External.Settings.StorageConfig + * @class OCA.Files_External.Settings.GlobalStorageConfig + * @augments OCA.Files_External.Settings.StorageConfig * * @classdesc Global external storage config */ @@ -359,10 +359,10 @@ var GlobalStorageConfig = function(id) { this.applicableGroups = []; }; /** - * @memberOf OCA.External.Settings + * @memberOf OCA.Files_External.Settings */ GlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype, - /** @lends OCA.External.Settings.GlobalStorageConfig.prototype */ { + /** @lends OCA.Files_External.Settings.GlobalStorageConfig.prototype */ { _url: 'apps/files_external/globalstorages', /** @@ -402,8 +402,8 @@ GlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype, }); /** - * @class OCA.External.Settings.UserStorageConfig - * @augments OCA.External.Settings.StorageConfig + * @class OCA.Files_External.Settings.UserStorageConfig + * @augments OCA.Files_External.Settings.StorageConfig * * @classdesc User external storage config */ @@ -411,13 +411,13 @@ var UserStorageConfig = function(id) { this.id = id; }; UserStorageConfig.prototype = _.extend({}, StorageConfig.prototype, - /** @lends OCA.External.Settings.UserStorageConfig.prototype */ { + /** @lends OCA.Files_External.Settings.UserStorageConfig.prototype */ { _url: 'apps/files_external/userstorages' }); /** - * @class OCA.External.Settings.UserGlobalStorageConfig - * @augments OCA.External.Settings.StorageConfig + * @class OCA.Files_External.Settings.UserGlobalStorageConfig + * @augments OCA.Files_External.Settings.StorageConfig * * @classdesc User external storage config */ @@ -425,13 +425,13 @@ var UserGlobalStorageConfig = function (id) { this.id = id; }; UserGlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype, - /** @lends OCA.External.Settings.UserStorageConfig.prototype */ { + /** @lends OCA.Files_External.Settings.UserStorageConfig.prototype */ { _url: 'apps/files_external/userglobalstorages' }); /** - * @class OCA.External.Settings.MountOptionsDropdown + * @class OCA.Files_External.Settings.MountOptionsDropdown * * @classdesc Dropdown for mount options * @@ -440,7 +440,7 @@ UserGlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype, var MountOptionsDropdown = function() { }; /** - * @memberof OCA.External.Settings + * @memberof OCA.Files_External.Settings */ MountOptionsDropdown.prototype = { /** @@ -462,7 +462,7 @@ MountOptionsDropdown.prototype = { MountOptionsDropdown._last.hide(); } - var $el = $(OCA.External.Templates.mountOptionsDropDown({ + var $el = $(OCA.Files_External.Templates.mountOptionsDropDown({ mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)'), mountOptionsEncryptLabel: t('files_external', 'Enable encryption'), mountOptionsPreviewsLabel: t('files_external', 'Enable previews'), @@ -549,7 +549,7 @@ MountOptionsDropdown.prototype = { }; /** - * @class OCA.External.Settings.MountConfigListView + * @class OCA.Files_External.Settings.MountConfigListView * * @classdesc Mount configuration list view * @@ -574,7 +574,7 @@ MountConfigListView.ParameterTypes = { }; /** - * @memberOf OCA.External.Settings + * @memberOf OCA.Files_External.Settings */ MountConfigListView.prototype = _.extend({ @@ -633,9 +633,9 @@ MountConfigListView.prototype = _.extend({ this.$el = $el; this._isPersonal = ($el.data('admin') !== true); if (this._isPersonal) { - this._storageConfigClass = OCA.External.Settings.UserStorageConfig; + this._storageConfigClass = OCA.Files_External.Settings.UserStorageConfig; } else { - this._storageConfigClass = OCA.External.Settings.GlobalStorageConfig; + this._storageConfigClass = OCA.Files_External.Settings.GlobalStorageConfig; } if (options && !_.isUndefined(options.userListLimit)) { @@ -1008,7 +1008,7 @@ MountConfigListView.prototype = _.extend({ * Gets the storage model from the given row * * @param $tr row element - * @return {OCA.External.StorageConfig} storage model instance + * @return {OCA.Files_External.StorageConfig} storage model instance */ getStorageConfig: function($tr) { var storageId = $tr.data('id'); @@ -1367,13 +1367,13 @@ $(document).ready(function() { }); // global instance - OCA.External.Settings.mountConfig = mountConfigListView; + OCA.Files_External.Settings.mountConfig = mountConfigListView; /** * Legacy * * @namespace - * @deprecated use OCA.External.Settings.mountConfig instead + * @deprecated use OCA.Files_External.Settings.mountConfig instead */ OC.MountConfig = { saveStorage: _.bind(mountConfigListView.saveStorageConfig, mountConfigListView) @@ -1382,14 +1382,14 @@ $(document).ready(function() { // export -OCA.External = OCA.External || {}; +OCA.Files_External = OCA.Files_External || {}; /** * @namespace */ -OCA.External.Settings = OCA.External.Settings || {}; +OCA.Files_External.Settings = OCA.Files_External.Settings || {}; -OCA.External.Settings.GlobalStorageConfig = GlobalStorageConfig; -OCA.External.Settings.UserStorageConfig = UserStorageConfig; -OCA.External.Settings.MountConfigListView = MountConfigListView; +OCA.Files_External.Settings.GlobalStorageConfig = GlobalStorageConfig; +OCA.Files_External.Settings.UserStorageConfig = UserStorageConfig; +OCA.Files_External.Settings.MountConfigListView = MountConfigListView; })(); diff --git a/apps/files_external/js/statusmanager.js b/apps/files_external/js/statusmanager.js index b8b5e1a9364..b4e89bd6232 100644 --- a/apps/files_external/js/statusmanager.js +++ b/apps/files_external/js/statusmanager.js @@ -14,15 +14,15 @@ /** @global Handlebars */ -if (!OCA.External) { - OCA.External = {}; +if (!OCA.Files_External) { + OCA.Files_External = {}; } -if (!OCA.External.StatusManager) { - OCA.External.StatusManager = {}; +if (!OCA.Files_External.StatusManager) { + OCA.Files_External.StatusManager = {}; } -OCA.External.StatusManager = { +OCA.Files_External.StatusManager = { mountStatus: null, mountPointList: null, @@ -209,18 +209,18 @@ OCA.External.StatusManager = { var mountPoint = mountData.mount_point; if (mountStatus.status > 0) { - var trElement = FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(mountPoint)); + var trElement = FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(mountPoint)); - var route = OCA.External.StatusManager.Utils.getIconRoute(trElement) + '-error'; + var route = OCA.Files_External.StatusManager.Utils.getIconRoute(trElement) + '-error'; - if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) { - OCA.External.StatusManager.Utils.showIconError(mountPoint, $.proxy(OCA.External.StatusManager.manageMountPointError, OCA.External.StatusManager), route); + if (OCA.Files_External.StatusManager.Utils.isCorrectViewAndRootFolder()) { + OCA.Files_External.StatusManager.Utils.showIconError(mountPoint, $.proxy(OCA.Files_External.StatusManager.manageMountPointError, OCA.Files_External.StatusManager), route); } return false; } else { - if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) { - OCA.External.StatusManager.Utils.restoreFolder(mountPoint); - OCA.External.StatusManager.Utils.toggleLink(mountPoint, true, true); + if (OCA.Files_External.StatusManager.Utils.isCorrectViewAndRootFolder()) { + OCA.Files_External.StatusManager.Utils.restoreFolder(mountPoint); + OCA.Files_External.StatusManager.Utils.toggleLink(mountPoint, true, true); } return true; } @@ -235,7 +235,7 @@ OCA.External.StatusManager = { processMountList: function (mountList) { var elementList = null; $.each(mountList, function (name, value) { - var trElement = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point)); + var trElement = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(value.mount_point) + '\"]'); //FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(value.mount_point)); trElement.attr('data-external-backend', value.backend); if (elementList) { elementList = elementList.add(trElement); @@ -245,14 +245,14 @@ OCA.External.StatusManager = { }); if (elementList instanceof $) { - if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) { + if (OCA.Files_External.StatusManager.Utils.isCorrectViewAndRootFolder()) { // Put their custom icon - OCA.External.StatusManager.Utils.changeFolderIcon(elementList); + OCA.Files_External.StatusManager.Utils.changeFolderIcon(elementList); // Save default view - OCA.External.StatusManager.Utils.storeDefaultFolderIconAndBgcolor(elementList); + OCA.Files_External.StatusManager.Utils.storeDefaultFolderIconAndBgcolor(elementList); // Disable row until check status elementList.addClass('externalDisabledRow'); - OCA.External.StatusManager.Utils.toggleLink(elementList.find('a.name'), false, false); + OCA.Files_External.StatusManager.Utils.toggleLink(elementList.find('a.name'), false, false); } } }, @@ -289,7 +289,7 @@ OCA.External.StatusManager = { ajaxQueue.push(queueElement); }); - var rolQueue = new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4, function () { + var rolQueue = new OCA.Files_External.StatusManager.RollingQueue(ajaxQueue, 4, function () { if (!self.notificationHasShown) { var showNotification = false; $.each(self.mountStatus, function (key, value) { @@ -335,7 +335,7 @@ OCA.External.StatusManager = { }; ajaxQueue.push(queueElement); }); - new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4).runQueue(); + new OCA.Files_External.StatusManager.RollingQueue(ajaxQueue, 4).runQueue(); }, @@ -392,7 +392,7 @@ OCA.External.StatusManager = { * @param mountData */ showCredentialsDialog: function (mountPoint, mountData) { - var dialog = $(OCA.External.Templates.credentialsDialog({ + var dialog = $(OCA.Files_External.Templates.credentialsDialog({ credentials_text: t('files_external', 'Please enter the credentials for the {mount} mount', { 'mount': mountPoint }), @@ -422,7 +422,7 @@ OCA.External.StatusManager = { OC.Notification.show(t('files_external', 'Credentials saved'), {type: 'error'}); dialog.ocdialog('close'); /* Trigger status check again */ - OCA.External.StatusManager.recheckConnectivityForMount([OC.basename(data.mountPoint)], true); + OCA.Files_External.StatusManager.recheckConnectivityForMount([OC.basename(data.mountPoint)], true); }, error: function () { $('.oc-dialog-close').show(); @@ -461,11 +461,11 @@ OCA.External.StatusManager = { } }; -OCA.External.StatusManager.Utils = { +OCA.Files_External.StatusManager.Utils = { showIconError: function (folder, clickAction, errorImageUrl) { var imageUrl = "url(" + errorImageUrl + ")"; - var trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); + var trFolder = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(folder)); this.changeFolderIcon(folder, imageUrl); this.toggleLink(folder, false, clickAction); trFolder.addClass('externalErroredRow'); @@ -479,7 +479,7 @@ OCA.External.StatusManager.Utils = { if (folder instanceof $) { trFolder = folder; } else { - trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); //$('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); + trFolder = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(folder)); //$('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); } trFolder.each(function () { var thisElement = $(this); @@ -505,8 +505,8 @@ OCA.External.StatusManager.Utils = { if (folder instanceof $) { trFolder = folder; } else { - // can't use here FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); return incorrect instance of filelist - trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); + // can't use here FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(folder)); return incorrect instance of filelist + trFolder = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); } trFolder.removeClass('externalErroredRow').removeClass('externalDisabledRow'); var tdChilds = trFolder.find("td.filename div.thumbnail"); @@ -526,14 +526,14 @@ OCA.External.StatusManager.Utils = { if (filename instanceof $) { //trElementList $.each(filename, function (index) { - route = OCA.External.StatusManager.Utils.getIconRoute($(this)); + route = OCA.Files_External.StatusManager.Utils.getIconRoute($(this)); $(this).attr("data-icon", route); $(this).find('td.filename div.thumbnail').css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline'); }); } else { file = $("#fileList tr[data-file=\"" + this.jqSelEscape(filename) + "\"] > td.filename div.thumbnail"); var parentTr = file.parents('tr:first'); - route = OCA.External.StatusManager.Utils.getIconRoute(parentTr); + route = OCA.Files_External.StatusManager.Utils.getIconRoute(parentTr); parentTr.attr("data-icon", route); file.css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline'); } diff --git a/apps/files_external/js/templates.js b/apps/files_external/js/templates.js index 067b3f5f5d7..cf1522334c5 100644 --- a/apps/files_external/js/templates.js +++ b/apps/files_external/js/templates.js @@ -1,5 +1,5 @@ (function() { - var template = Handlebars.template, templates = OCA.External.Templates = OCA.External.Templates || {}; + var template = Handlebars.template, templates = OCA.Files_External.Templates = OCA.Files_External.Templates || {}; templates['credentialsDialog'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; diff --git a/apps/files_external/tests/appSpec.js b/apps/files_external/tests/appSpec.js index 43902d1c1d0..a834d96e2c0 100644 --- a/apps/files_external/tests/appSpec.js +++ b/apps/files_external/tests/appSpec.js @@ -19,8 +19,8 @@ * */ -describe('OCA.External.App tests', function() { - var App = OCA.External.App; +describe('OCA.Files_External.App tests', function() { + var App = OCA.Files_External.App; var fileList; beforeEach(function() { diff --git a/apps/files_external/tests/js/mountsfilelistSpec.js b/apps/files_external/tests/js/mountsfilelistSpec.js index feea68cf346..fe2fd8dec84 100644 --- a/apps/files_external/tests/js/mountsfilelistSpec.js +++ b/apps/files_external/tests/js/mountsfilelistSpec.js @@ -8,7 +8,7 @@ * */ -describe('OCA.External.FileList tests', function() { +describe('OCA.Files_External.FileList tests', function() { var testFiles, alertStub, notificationStub, fileList; beforeEach(function() { @@ -62,7 +62,7 @@ describe('OCA.External.FileList tests', function() { var ocsResponse; beforeEach(function() { - fileList = new OCA.External.FileList( + fileList = new OCA.Files_External.FileList( $('#app-content-container') ); diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js index 57ad4550993..e004871650c 100644 --- a/apps/files_external/tests/js/settingsSpec.js +++ b/apps/files_external/tests/js/settingsSpec.js @@ -8,7 +8,7 @@ * */ -describe('OCA.External.Settings tests', function() { +describe('OCA.Files_External.Settings tests', function() { var clock; var select2Stub; var select2ApplicableUsers; @@ -156,7 +156,7 @@ describe('OCA.External.Settings tests', function() { beforeEach(function() { var $el = $('#externalStorage'); - view = new OCA.External.Settings.MountConfigListView($el, {encryptionEnabled: false}); + view = new OCA.Files_External.Settings.MountConfigListView($el, {encryptionEnabled: false}); }); afterEach(function() { view = null; diff --git a/apps/files_sharing/css/sharetabview.scss b/apps/files_sharing/css/sharetabview.scss index 14be9562228..0ca99ddc8f7 100644 --- a/apps/files_sharing/css/sharetabview.scss +++ b/apps/files_sharing/css/sharetabview.scss @@ -4,6 +4,10 @@ .share-autocomplete-item { display: flex; + + &.merged { + margin-left: 32px; + } .autocomplete-item-text { margin-left: 10px; margin-right: 10px; @@ -12,6 +16,27 @@ overflow: hidden; line-height: 32px; vertical-align: middle; + flex-grow: 1; + .ui-state-highlight { + border: none; + margin: 0; + } + } + &.with-description { + .autocomplete-item-text { + line-height: 100%; + } + } + .autocomplete-item-details { + display: block; + line-height: 130%; + font-size: 90%; + opacity: 0.7; + } + + .icon { + opacity: .7; + margin-right: 7px; } } @@ -26,7 +51,6 @@ top: 0px; } .shareWithConfirm, - .clipboardButton, .linkPass .icon-loading-small { position: absolute; right: 2px; @@ -49,21 +73,17 @@ .datepicker { margin-left: 35px; } - .clipboardButton { - position: relative; - top: initial; - right: initial; - padding: 0; - } .share-add { input.share-note-delete { - display: none; border: none; background-color: transparent; width: 44px !important; padding: 0; flex: 0 0 44px; margin-left: auto; + &.hidden { + display: none; + } } } // note @@ -98,6 +118,11 @@ margin-bottom: 10px; } } + + /* Border above last entry '+ Add another share' to separate it from current link settings */ + .new-share { + border-top: 1px solid var(--color-border); + } } .linkPass .icon-loading-small { margin-right: 0px; @@ -157,7 +182,7 @@ .avatar { width: 32px; height: 32px; - background-color: var(--color-background-darker); + background-color: var(--color-primary); } } .unshare img { @@ -169,31 +194,29 @@ display: flex; align-items: center; white-space: nowrap; - // can edit label - > .shareOption > label { - padding: 13px; - padding-right: 0; - } - // more menu - > .share-menu { - position: relative; + + // icons + > .icon:not(.hidden), + .share-menu > .icon:not(.hidden) { + padding: 14px; + height: 44px; + width: 44px; + opacity: .5; display: block; - .icon-more { - padding: 14px; - height: 44px; - width: 44px; - opacity: .5; - display: block; - cursor: pointer; - } + cursor: pointer; + &:hover, &:focus, &:active { - .icon-more { - opacity: .7;; - } + opacity: .7;; } } + + // more menu + > .share-menu { + position: relative; + display: block; + } } .username { padding: 0 8px; @@ -204,8 +227,8 @@ } .ui-autocomplete { - /* limit dropdown height to 4 1/2 entries */ - max-height: calc(36px * 4.5);; + /* limit dropdown height to 6 1/2 entries */ + max-height: calc(36px * 6.5); overflow-y: auto; overflow-x: hidden; z-index: 1550 !important; @@ -244,4 +267,4 @@ .resharerInfoView.subView { position: relative; -}
\ No newline at end of file +} diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 68529fd882f..b02c6e3d9ee 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -193,15 +193,15 @@ var $tr = fileList.findFileEl(fileInfoModel.get('name')); // We count email shares as link share - var hasLinkShare = shareModel.hasLinkShare(); + var hasLinkShares = shareModel.hasLinkShares(); shareModel.get('shares').forEach(function (share) { if (share.share_type === OC.Share.SHARE_TYPE_EMAIL) { - hasLinkShare = true; + hasLinkShares = true; } }); OCA.Sharing.Util._updateFileListDataAttributes(fileList, $tr, shareModel); - if (!OCA.Sharing.Util._updateFileActionIcon($tr, shareModel.hasUserShares(), hasLinkShare)) { + if (!OCA.Sharing.Util._updateFileActionIcon($tr, shareModel.hasUserShares(), hasLinkShares)) { // remove icon, if applicable OC.Share.markFileAsShared($tr, false, false); } @@ -249,15 +249,15 @@ * * @param $tr file element of the file to update * @param {boolean} hasUserShares true if a user share exists - * @param {boolean} hasLinkShare true if a link share exists + * @param {boolean} hasLinkShares true if a link share exists * * @return {boolean} true if the icon was set, false otherwise */ - _updateFileActionIcon: function($tr, hasUserShares, hasLinkShare) { + _updateFileActionIcon: function($tr, hasUserShares, hasLinkShares) { // if the statuses are loaded already, use them for the icon // (needed when scrolling to the next page) - if (hasUserShares || hasLinkShare || $tr.attr('data-share-recipient-data') || $tr.attr('data-share-owner')) { - OC.Share.markFileAsShared($tr, true, hasLinkShare); + if (hasUserShares || hasLinkShares || $tr.attr('data-share-recipient-data') || $tr.attr('data-share-owner')) { + OC.Share.markFileAsShared($tr, true, hasLinkShares); return true; } return false; diff --git a/apps/files_sharing/l10n/cs.js b/apps/files_sharing/l10n/cs.js index fdc18a2da3f..d1abeb033bc 100644 --- a/apps/files_sharing/l10n/cs.js +++ b/apps/files_sharing/l10n/cs.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Sdílení veřejným odkazem je zakázáno správcem", "Public upload disabled by the administrator" : "Nahrávání veřejností zakázáno správcem", "Public upload is only possible for publicly shared folders" : "Veřejné nahrávání je možné pouze do veřejně sdílených šložek", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Sdílení %s posláním hesla přes Nextcloud Talk se nezdařilo, protože Nextcloud Talk není zapnutý", "Invalid date, date format must be YYYY-MM-DD" : "Neplatné datum – je třeba, aby jeho formát byl RRRR-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Sdílení %1$s se nezdařilo, protože podpůrná vrstva nepodporuje typ sdílení %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Sdílení %s posláním hesla přes Nextcloud Talk se nezdařilo, protože Nextcloud Talk není zapnutý", "You cannot share to a Circle if the app is not enabled" : "Do okruhu nemůžete sdílet, pokud není aplikace zapnuta", "Please specify a valid circle" : "Zadejte platný okruh", "Sharing %s failed because the back end does not support room shares" : "Sdílení %s se nezdařilo protože podpůrná vrstva nepodporuje sdílení místností", diff --git a/apps/files_sharing/l10n/cs.json b/apps/files_sharing/l10n/cs.json index 877742a4a50..415c2b53b5f 100644 --- a/apps/files_sharing/l10n/cs.json +++ b/apps/files_sharing/l10n/cs.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Sdílení veřejným odkazem je zakázáno správcem", "Public upload disabled by the administrator" : "Nahrávání veřejností zakázáno správcem", "Public upload is only possible for publicly shared folders" : "Veřejné nahrávání je možné pouze do veřejně sdílených šložek", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Sdílení %s posláním hesla přes Nextcloud Talk se nezdařilo, protože Nextcloud Talk není zapnutý", "Invalid date, date format must be YYYY-MM-DD" : "Neplatné datum – je třeba, aby jeho formát byl RRRR-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Sdílení %1$s se nezdařilo, protože podpůrná vrstva nepodporuje typ sdílení %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Sdílení %s posláním hesla přes Nextcloud Talk se nezdařilo, protože Nextcloud Talk není zapnutý", "You cannot share to a Circle if the app is not enabled" : "Do okruhu nemůžete sdílet, pokud není aplikace zapnuta", "Please specify a valid circle" : "Zadejte platný okruh", "Sharing %s failed because the back end does not support room shares" : "Sdílení %s se nezdařilo protože podpůrná vrstva nepodporuje sdílení místností", diff --git a/apps/files_sharing/l10n/de.js b/apps/files_sharing/l10n/de.js index acac2952093..84b463aca49 100644 --- a/apps/files_sharing/l10n/de.js +++ b/apps/files_sharing/l10n/de.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Die öffentliche Freigabe von Links ist durch den Administrator deaktiviert", "Public upload disabled by the administrator" : "Das öffentliche Hochladen ist durch den Administrator deaktiviert", "Public upload is only possible for publicly shared folders" : "Das öffentliche Hochladen ist nur für öffentlich freigegebene Ordner erlaubt", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "Invalid date, date format must be YYYY-MM-DD" : "Ungültiges Datum, das Datumsformat muss JJJJ-MM-TT sein", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Freigabe von %1$s fehlgeschlagen, da das Backend die Freigabe vom Typ %2$s nicht erlaubt", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "You cannot share to a Circle if the app is not enabled" : "Du kannst nichts mit einem Kreis teilen, wenn die App nicht aktiviert ist", "Please specify a valid circle" : "Bitte einen gültigen Kreis angeben", "Sharing %s failed because the back end does not support room shares" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe von Räumen nicht unterstützt", diff --git a/apps/files_sharing/l10n/de.json b/apps/files_sharing/l10n/de.json index 97d761b3bd5..5b9a6e862de 100644 --- a/apps/files_sharing/l10n/de.json +++ b/apps/files_sharing/l10n/de.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Die öffentliche Freigabe von Links ist durch den Administrator deaktiviert", "Public upload disabled by the administrator" : "Das öffentliche Hochladen ist durch den Administrator deaktiviert", "Public upload is only possible for publicly shared folders" : "Das öffentliche Hochladen ist nur für öffentlich freigegebene Ordner erlaubt", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "Invalid date, date format must be YYYY-MM-DD" : "Ungültiges Datum, das Datumsformat muss JJJJ-MM-TT sein", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Freigabe von %1$s fehlgeschlagen, da das Backend die Freigabe vom Typ %2$s nicht erlaubt", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "You cannot share to a Circle if the app is not enabled" : "Du kannst nichts mit einem Kreis teilen, wenn die App nicht aktiviert ist", "Please specify a valid circle" : "Bitte einen gültigen Kreis angeben", "Sharing %s failed because the back end does not support room shares" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe von Räumen nicht unterstützt", diff --git a/apps/files_sharing/l10n/de_DE.js b/apps/files_sharing/l10n/de_DE.js index 04090d4fff5..839cfe989e7 100644 --- a/apps/files_sharing/l10n/de_DE.js +++ b/apps/files_sharing/l10n/de_DE.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Die öffentliche Freigabe von Links ist durch den Administrator deaktiviert", "Public upload disabled by the administrator" : "Das öffentliche Hochladen ist durch den Administrator deaktiviert", "Public upload is only possible for publicly shared folders" : "Das öffentliche Hochladen ist nur für öffentlich freigegebene Ordner erlaubt", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "Invalid date, date format must be YYYY-MM-DD" : "Ungültiges Datum, das Datumsformat muss JJJJ-MM-TT sein", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Freigabe von %1$s fehlgeschlagen, da das Backend die Freigabe vom Typ %2$s nicht erlaubt", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "You cannot share to a Circle if the app is not enabled" : "Sie können nichts mit einem Kreis teilen, wenn die App nicht aktiviert ist", "Please specify a valid circle" : "Bitte einen gültigen Kreis angeben", "Sharing %s failed because the back end does not support room shares" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe von Räumen nicht unterstützt", diff --git a/apps/files_sharing/l10n/de_DE.json b/apps/files_sharing/l10n/de_DE.json index 88cbc15a831..15df40394f1 100644 --- a/apps/files_sharing/l10n/de_DE.json +++ b/apps/files_sharing/l10n/de_DE.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Die öffentliche Freigabe von Links ist durch den Administrator deaktiviert", "Public upload disabled by the administrator" : "Das öffentliche Hochladen ist durch den Administrator deaktiviert", "Public upload is only possible for publicly shared folders" : "Das öffentliche Hochladen ist nur für öffentlich freigegebene Ordner erlaubt", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "Invalid date, date format must be YYYY-MM-DD" : "Ungültiges Datum, das Datumsformat muss JJJJ-MM-TT sein", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Freigabe von %1$s fehlgeschlagen, da das Backend die Freigabe vom Typ %2$s nicht erlaubt", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "%s Freigeben: Senden des Passwortes über Nextcloud Talk gescheitert, da Nextcloud Talk nicht verfügbar ist", "You cannot share to a Circle if the app is not enabled" : "Sie können nichts mit einem Kreis teilen, wenn die App nicht aktiviert ist", "Please specify a valid circle" : "Bitte einen gültigen Kreis angeben", "Sharing %s failed because the back end does not support room shares" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe von Räumen nicht unterstützt", diff --git a/apps/files_sharing/l10n/es.js b/apps/files_sharing/l10n/es.js index 43f9c5f3ce7..1ddf9f4fb29 100644 --- a/apps/files_sharing/l10n/es.js +++ b/apps/files_sharing/l10n/es.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Compartir enlaces de forma pública está deshabilitado por el administrador", "Public upload disabled by the administrator" : "La subida pública está deshabilitado por el administrador", "Public upload is only possible for publicly shared folders" : "La subida publica solo es posible para las carpetas publicas compartidas", - "Invalid date, date format must be YYYY-MM-DD" : "Fecha inválida, el formato de las fechas debe ser YYYY-MM-DD", - "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Compartir %1$s ha fallado porque el motor no permite compartidos del tipo %2$s", "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Compartir %s enviando la contraseña por Nextcloud Talk ha falllado porque Nextcloud Talk no está activado", + "Invalid date, date format must be YYYY-MM-DD" : "Fecha inválida, el formato de las fechas debe ser YYYY-MM-DD", + "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Compartir %1$s ha fallado porque el backend no permite compartidos del tipo %2$s", "You cannot share to a Circle if the app is not enabled" : "No puede compartir a un Circulo si la aplicación no esta activada", "Please specify a valid circle" : "Por favor especifique un circulo valido", "Sharing %s failed because the back end does not support room shares" : "Compartir %s ha fallado porque el backend no soporta habitaciones compartidas", diff --git a/apps/files_sharing/l10n/es.json b/apps/files_sharing/l10n/es.json index 00fa8870b72..8a7b4f40259 100644 --- a/apps/files_sharing/l10n/es.json +++ b/apps/files_sharing/l10n/es.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Compartir enlaces de forma pública está deshabilitado por el administrador", "Public upload disabled by the administrator" : "La subida pública está deshabilitado por el administrador", "Public upload is only possible for publicly shared folders" : "La subida publica solo es posible para las carpetas publicas compartidas", - "Invalid date, date format must be YYYY-MM-DD" : "Fecha inválida, el formato de las fechas debe ser YYYY-MM-DD", - "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Compartir %1$s ha fallado porque el motor no permite compartidos del tipo %2$s", "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Compartir %s enviando la contraseña por Nextcloud Talk ha falllado porque Nextcloud Talk no está activado", + "Invalid date, date format must be YYYY-MM-DD" : "Fecha inválida, el formato de las fechas debe ser YYYY-MM-DD", + "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Compartir %1$s ha fallado porque el backend no permite compartidos del tipo %2$s", "You cannot share to a Circle if the app is not enabled" : "No puede compartir a un Circulo si la aplicación no esta activada", "Please specify a valid circle" : "Por favor especifique un circulo valido", "Sharing %s failed because the back end does not support room shares" : "Compartir %s ha fallado porque el backend no soporta habitaciones compartidas", diff --git a/apps/files_sharing/l10n/fr.js b/apps/files_sharing/l10n/fr.js index e6549b0cdf5..e2976d939f0 100644 --- a/apps/files_sharing/l10n/fr.js +++ b/apps/files_sharing/l10n/fr.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Le partage de lien public a été désactivé par l'administrateur", "Public upload disabled by the administrator" : "Téléversement public désactivé par l'administrateur", "Public upload is only possible for publicly shared folders" : "Le téléversement public est possible uniquement pour les dossiers partagés publiquement", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Partager %s en envoyant le mot de passe par Nextcloud Talk a échoué car Nextcloud Talk n'est pas activé.", "Invalid date, date format must be YYYY-MM-DD" : "Date non valide, le format doit être DD/MM/YYYY", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Le partage %1$s a échoué parce que l'infrastructure n'autorise pas les partages du type %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Partager %s en envoyant le mot de passe par Nextcloud Talk a échoué car Nextcloud Talk n'est pas activé.", "You cannot share to a Circle if the app is not enabled" : "Vous ne pouvez pas partager au Cercle si l'application n'est pas activée", "Please specify a valid circle" : "Veuillez entrer un cercle valide", "Sharing %s failed because the back end does not support room shares" : "Le partage %s a échoué parce que l'arrière-plan ne prend pas en charge les partages.", diff --git a/apps/files_sharing/l10n/fr.json b/apps/files_sharing/l10n/fr.json index da6f68c246a..000b4bac874 100644 --- a/apps/files_sharing/l10n/fr.json +++ b/apps/files_sharing/l10n/fr.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Le partage de lien public a été désactivé par l'administrateur", "Public upload disabled by the administrator" : "Téléversement public désactivé par l'administrateur", "Public upload is only possible for publicly shared folders" : "Le téléversement public est possible uniquement pour les dossiers partagés publiquement", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Partager %s en envoyant le mot de passe par Nextcloud Talk a échoué car Nextcloud Talk n'est pas activé.", "Invalid date, date format must be YYYY-MM-DD" : "Date non valide, le format doit être DD/MM/YYYY", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Le partage %1$s a échoué parce que l'infrastructure n'autorise pas les partages du type %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Partager %s en envoyant le mot de passe par Nextcloud Talk a échoué car Nextcloud Talk n'est pas activé.", "You cannot share to a Circle if the app is not enabled" : "Vous ne pouvez pas partager au Cercle si l'application n'est pas activée", "Please specify a valid circle" : "Veuillez entrer un cercle valide", "Sharing %s failed because the back end does not support room shares" : "Le partage %s a échoué parce que l'arrière-plan ne prend pas en charge les partages.", diff --git a/apps/files_sharing/l10n/is.js b/apps/files_sharing/l10n/is.js index cc1cc03ae39..93c678cdede 100644 --- a/apps/files_sharing/l10n/is.js +++ b/apps/files_sharing/l10n/is.js @@ -88,15 +88,18 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Deiling opinberra sameignartengla hefur verið gerð óvirk af kerfisstjóra.", "Public upload disabled by the administrator" : "Opinber innsending hefur verið gerð óvirk af kerfisstjóra.", "Public upload is only possible for publicly shared folders" : "Opinber innsending er einungis möguleg í möppur sem er deilt opinberlega", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Deiling á %s með því að senda lykilorð með Nextcloud Talk mistókst því að Nextcloud Talk er ekki virkt", "Invalid date, date format must be YYYY-MM-DD" : "Ógild dagsetning, dagsetningasniðið verður að vera ÁÁÁÁ-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Deiling %1$s mistókst, því bakvinnslukerfið leyfir ekki sameignir af gerðinni %2$s", "You cannot share to a Circle if the app is not enabled" : "Þú getur ekki deilt með hring ef forritið er ekki virkt", "Please specify a valid circle" : "Settu inn gildan hring", + "Sharing %s failed because the back end does not support room shares" : "Deiling %s mistókst því bakvinnslukerfið leyfir ekki spjallsvæðasameignir", "Unknown share type" : "Óþekkt tegund sameignar", "Not a directory" : "Er ekki mappa", "Could not lock path" : "Gat ekki læst slóð", "Wrong or no update parameter given" : "Rangt eða ekkert uppfærsluviðfang gefið", "Can't change permissions for public share links" : "Ekki tókst að breyta aðgangsheimildum fyrir opinbera deilingartengla", + "Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Deiling með því að senda lykilorð með Nextcloud Talk mistókst því að Nextcloud Talk er ekki virkt", "Cannot increase permissions" : "Get ekki aukið aðgangsheimildir", "shared by %s" : "Deilt af %s", "Direct link" : "Beinn tengill", diff --git a/apps/files_sharing/l10n/is.json b/apps/files_sharing/l10n/is.json index c984df71929..f88598bfa1b 100644 --- a/apps/files_sharing/l10n/is.json +++ b/apps/files_sharing/l10n/is.json @@ -86,15 +86,18 @@ "Public link sharing is disabled by the administrator" : "Deiling opinberra sameignartengla hefur verið gerð óvirk af kerfisstjóra.", "Public upload disabled by the administrator" : "Opinber innsending hefur verið gerð óvirk af kerfisstjóra.", "Public upload is only possible for publicly shared folders" : "Opinber innsending er einungis möguleg í möppur sem er deilt opinberlega", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Deiling á %s með því að senda lykilorð með Nextcloud Talk mistókst því að Nextcloud Talk er ekki virkt", "Invalid date, date format must be YYYY-MM-DD" : "Ógild dagsetning, dagsetningasniðið verður að vera ÁÁÁÁ-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Deiling %1$s mistókst, því bakvinnslukerfið leyfir ekki sameignir af gerðinni %2$s", "You cannot share to a Circle if the app is not enabled" : "Þú getur ekki deilt með hring ef forritið er ekki virkt", "Please specify a valid circle" : "Settu inn gildan hring", + "Sharing %s failed because the back end does not support room shares" : "Deiling %s mistókst því bakvinnslukerfið leyfir ekki spjallsvæðasameignir", "Unknown share type" : "Óþekkt tegund sameignar", "Not a directory" : "Er ekki mappa", "Could not lock path" : "Gat ekki læst slóð", "Wrong or no update parameter given" : "Rangt eða ekkert uppfærsluviðfang gefið", "Can't change permissions for public share links" : "Ekki tókst að breyta aðgangsheimildum fyrir opinbera deilingartengla", + "Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Deiling með því að senda lykilorð með Nextcloud Talk mistókst því að Nextcloud Talk er ekki virkt", "Cannot increase permissions" : "Get ekki aukið aðgangsheimildir", "shared by %s" : "Deilt af %s", "Direct link" : "Beinn tengill", diff --git a/apps/files_sharing/l10n/it.js b/apps/files_sharing/l10n/it.js index cbc56eb8fca..0b84f6f25c0 100644 --- a/apps/files_sharing/l10n/it.js +++ b/apps/files_sharing/l10n/it.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "La condivisione pubblica di collegamenti è disabilitata dall'amministratore", "Public upload disabled by the administrator" : "Caricamento pubblico disabilitato dall'amministratore", "Public upload is only possible for publicly shared folders" : "Il caricamento pubblico è possibile solo per cartelle condivise pubblicamente", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "La condivisione di %s tramite invio della password da Nextcloud Talk non è riuscito poiché Nextcloud Talk non è abilitato", "Invalid date, date format must be YYYY-MM-DD" : "Data non valida, il formato della data deve essere YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Condivisione di %1$s non riuscita poiché il motore non consente condivisioni del tipo %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "La condivisione di %s tramite invio della password da Nextcloud Talk non è riuscito poiché Nextcloud Talk non è abilitato", "You cannot share to a Circle if the app is not enabled" : "Non puoi condividere con una cerchia se l'applicazione non è abilitata", "Please specify a valid circle" : "Specifica una cerchia valida", "Sharing %s failed because the back end does not support room shares" : "Condivisione di %s non riuscita poiché il motore non supporta condivisioni di stanza", diff --git a/apps/files_sharing/l10n/it.json b/apps/files_sharing/l10n/it.json index 0a9071fd9ba..a2147b93268 100644 --- a/apps/files_sharing/l10n/it.json +++ b/apps/files_sharing/l10n/it.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "La condivisione pubblica di collegamenti è disabilitata dall'amministratore", "Public upload disabled by the administrator" : "Caricamento pubblico disabilitato dall'amministratore", "Public upload is only possible for publicly shared folders" : "Il caricamento pubblico è possibile solo per cartelle condivise pubblicamente", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "La condivisione di %s tramite invio della password da Nextcloud Talk non è riuscito poiché Nextcloud Talk non è abilitato", "Invalid date, date format must be YYYY-MM-DD" : "Data non valida, il formato della data deve essere YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Condivisione di %1$s non riuscita poiché il motore non consente condivisioni del tipo %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "La condivisione di %s tramite invio della password da Nextcloud Talk non è riuscito poiché Nextcloud Talk non è abilitato", "You cannot share to a Circle if the app is not enabled" : "Non puoi condividere con una cerchia se l'applicazione non è abilitata", "Please specify a valid circle" : "Specifica una cerchia valida", "Sharing %s failed because the back end does not support room shares" : "Condivisione di %s non riuscita poiché il motore non supporta condivisioni di stanza", diff --git a/apps/files_sharing/l10n/nl.js b/apps/files_sharing/l10n/nl.js index 3c2f1aec70c..c9274091686 100644 --- a/apps/files_sharing/l10n/nl.js +++ b/apps/files_sharing/l10n/nl.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Delen van openbare links is uitgeschakeld door de beheerder", "Public upload disabled by the administrator" : "Publieke upload uitgeschakeld door de systeembeheerder", "Public upload is only possible for publicly shared folders" : "Publieke upload is alleen mogelijk voor publiek gedeelde mappen", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Delen %s versturen van het wachtwoord via Nextcloud Talk is mislukt omdat Nextcloud Talk niet is ingeschakeld", "Invalid date, date format must be YYYY-MM-DD" : "Ongeldige datum, datumnotatie moet in de vorm YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Delen van %1$s mislukte omdat de backend het delen van type %2$s niet ondersteunt", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Delen %s versturen van het wachtwoord via Nextcloud Talk is mislukt omdat Nextcloud Talk niet is ingeschakeld", "You cannot share to a Circle if the app is not enabled" : "Je kunt niets met een Kring delen als de app niet is ingeschakeld.", "Please specify a valid circle" : "Geef een geldige kring op", "Sharing %s failed because the back end does not support room shares" : "Delen van %s mislukte omdat de backend het delen in ruimtes niet ondersteunt", diff --git a/apps/files_sharing/l10n/nl.json b/apps/files_sharing/l10n/nl.json index 62816b3edb5..e274526c38a 100644 --- a/apps/files_sharing/l10n/nl.json +++ b/apps/files_sharing/l10n/nl.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Delen van openbare links is uitgeschakeld door de beheerder", "Public upload disabled by the administrator" : "Publieke upload uitgeschakeld door de systeembeheerder", "Public upload is only possible for publicly shared folders" : "Publieke upload is alleen mogelijk voor publiek gedeelde mappen", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Delen %s versturen van het wachtwoord via Nextcloud Talk is mislukt omdat Nextcloud Talk niet is ingeschakeld", "Invalid date, date format must be YYYY-MM-DD" : "Ongeldige datum, datumnotatie moet in de vorm YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Delen van %1$s mislukte omdat de backend het delen van type %2$s niet ondersteunt", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Delen %s versturen van het wachtwoord via Nextcloud Talk is mislukt omdat Nextcloud Talk niet is ingeschakeld", "You cannot share to a Circle if the app is not enabled" : "Je kunt niets met een Kring delen als de app niet is ingeschakeld.", "Please specify a valid circle" : "Geef een geldige kring op", "Sharing %s failed because the back end does not support room shares" : "Delen van %s mislukte omdat de backend het delen in ruimtes niet ondersteunt", diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js index beca0931e1a..ff8571fe55f 100644 --- a/apps/files_sharing/l10n/pl.js +++ b/apps/files_sharing/l10n/pl.js @@ -88,8 +88,8 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Udostępnianie linków publicznych zostało zablokowane przez twojego administratora", "Public upload disabled by the administrator" : "Publiczne wczytywanie zostało zablokowane przez twojego administratora", "Public upload is only possible for publicly shared folders" : "Publiczne wczytywanie jest możliwe wyłącznie do katalogów publicznych", - "Invalid date, date format must be YYYY-MM-DD" : "Nieprawidłowa data, format daty musi być w formacie YYYY-MM-DD", "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Udostępnianie %s wysyłanie hasła przez Nextcloud Talk nie powiodło się, ponieważ usługa Nextcloud Talk nie jest włączona", + "Invalid date, date format must be YYYY-MM-DD" : "Nieprawidłowa data, format daty musi być w formacie YYYY-MM-DD", "You cannot share to a Circle if the app is not enabled" : "Nie możesz udostępnić do Kręgów jeśli aplikacja jest wyłączona", "Please specify a valid circle" : "Proszę podać właściwy krąg", "Unknown share type" : "Nieznany typ udziału", diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json index 3deb0c8e80a..f8bc173b35c 100644 --- a/apps/files_sharing/l10n/pl.json +++ b/apps/files_sharing/l10n/pl.json @@ -86,8 +86,8 @@ "Public link sharing is disabled by the administrator" : "Udostępnianie linków publicznych zostało zablokowane przez twojego administratora", "Public upload disabled by the administrator" : "Publiczne wczytywanie zostało zablokowane przez twojego administratora", "Public upload is only possible for publicly shared folders" : "Publiczne wczytywanie jest możliwe wyłącznie do katalogów publicznych", - "Invalid date, date format must be YYYY-MM-DD" : "Nieprawidłowa data, format daty musi być w formacie YYYY-MM-DD", "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Udostępnianie %s wysyłanie hasła przez Nextcloud Talk nie powiodło się, ponieważ usługa Nextcloud Talk nie jest włączona", + "Invalid date, date format must be YYYY-MM-DD" : "Nieprawidłowa data, format daty musi być w formacie YYYY-MM-DD", "You cannot share to a Circle if the app is not enabled" : "Nie możesz udostępnić do Kręgów jeśli aplikacja jest wyłączona", "Please specify a valid circle" : "Proszę podać właściwy krąg", "Unknown share type" : "Nieznany typ udziału", diff --git a/apps/files_sharing/l10n/pt_BR.js b/apps/files_sharing/l10n/pt_BR.js index 52db057cdfc..59b488e5cfb 100644 --- a/apps/files_sharing/l10n/pt_BR.js +++ b/apps/files_sharing/l10n/pt_BR.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "O compartilhamento por link público foi desativado pelo administrador", "Public upload disabled by the administrator" : "O envio público foi desativado pelo administrador", "Public upload is only possible for publicly shared folders" : "O envio público só é possível para pastas compartilhadas publicamente", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "O compartilhamento %s falhou ao enviar a senha ao Nextcloud Talk porque este não está ativado", "Invalid date, date format must be YYYY-MM-DD" : "Data inválida, o formato da data deve ser YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "O compartilhamento %1$s falhou porque a infraestrutura não permite compartilhamentos do tipo %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "O compartilhamento %s falhou ao enviar a senha ao Nextcloud Talk porque este não está ativado", "You cannot share to a Circle if the app is not enabled" : "Você não pode compartilhar para um círculo se o aplicativo não está habilitado", "Please specify a valid circle" : "Por favor especifique um círculo válido", "Sharing %s failed because the back end does not support room shares" : "Falhou ao compartilhar %s porque o sistema não suporta compartilhamento de salas", diff --git a/apps/files_sharing/l10n/pt_BR.json b/apps/files_sharing/l10n/pt_BR.json index 78fe47c4ac1..f73dd0f14f9 100644 --- a/apps/files_sharing/l10n/pt_BR.json +++ b/apps/files_sharing/l10n/pt_BR.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "O compartilhamento por link público foi desativado pelo administrador", "Public upload disabled by the administrator" : "O envio público foi desativado pelo administrador", "Public upload is only possible for publicly shared folders" : "O envio público só é possível para pastas compartilhadas publicamente", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "O compartilhamento %s falhou ao enviar a senha ao Nextcloud Talk porque este não está ativado", "Invalid date, date format must be YYYY-MM-DD" : "Data inválida, o formato da data deve ser YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "O compartilhamento %1$s falhou porque a infraestrutura não permite compartilhamentos do tipo %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "O compartilhamento %s falhou ao enviar a senha ao Nextcloud Talk porque este não está ativado", "You cannot share to a Circle if the app is not enabled" : "Você não pode compartilhar para um círculo se o aplicativo não está habilitado", "Please specify a valid circle" : "Por favor especifique um círculo válido", "Sharing %s failed because the back end does not support room shares" : "Falhou ao compartilhar %s porque o sistema não suporta compartilhamento de salas", diff --git a/apps/files_sharing/l10n/ru.js b/apps/files_sharing/l10n/ru.js index 35a719de06b..7fcfb301559 100644 --- a/apps/files_sharing/l10n/ru.js +++ b/apps/files_sharing/l10n/ru.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Возможность предоставления общего доступа созданием общедоступных ссылок отключена администратором", "Public upload disabled by the administrator" : "Загрузка в общедоступную папку запрещена администратором", "Public upload is only possible for publicly shared folders" : "Общедоступная загрузка возможна только в общедоступные папки", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Не удалось отправить пароль для доступа к «%s»: приложение Nextcloud Talk отключено.", "Invalid date, date format must be YYYY-MM-DD" : "Неверная дата, формат даты должен быть ГГГГ-ММ-ДД", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Не удалось предоставить общий доступ к «%1$s», поскольку механизм удалённого обмена не разрешает публикации типа %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Не удалось отправить пароль для доступа к «%s»: приложение Nextcloud Talk отключено.", "You cannot share to a Circle if the app is not enabled" : "Вы не можете поделиться с кругом, если приложение «Круг» не включено", "Please specify a valid circle" : "Укажите верный круг", "Sharing %s failed because the back end does not support room shares" : "Не удалось предоставить общий доступ к «%s» поскольку механизм обмена не поддерживает общий доступ такого типа", diff --git a/apps/files_sharing/l10n/ru.json b/apps/files_sharing/l10n/ru.json index fc31b2380d7..47a1289cd42 100644 --- a/apps/files_sharing/l10n/ru.json +++ b/apps/files_sharing/l10n/ru.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Возможность предоставления общего доступа созданием общедоступных ссылок отключена администратором", "Public upload disabled by the administrator" : "Загрузка в общедоступную папку запрещена администратором", "Public upload is only possible for publicly shared folders" : "Общедоступная загрузка возможна только в общедоступные папки", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Не удалось отправить пароль для доступа к «%s»: приложение Nextcloud Talk отключено.", "Invalid date, date format must be YYYY-MM-DD" : "Неверная дата, формат даты должен быть ГГГГ-ММ-ДД", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Не удалось предоставить общий доступ к «%1$s», поскольку механизм удалённого обмена не разрешает публикации типа %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Не удалось отправить пароль для доступа к «%s»: приложение Nextcloud Talk отключено.", "You cannot share to a Circle if the app is not enabled" : "Вы не можете поделиться с кругом, если приложение «Круг» не включено", "Please specify a valid circle" : "Укажите верный круг", "Sharing %s failed because the back end does not support room shares" : "Не удалось предоставить общий доступ к «%s» поскольку механизм обмена не поддерживает общий доступ такого типа", diff --git a/apps/files_sharing/l10n/sk.js b/apps/files_sharing/l10n/sk.js index 84d451cfb94..b09abb71ee6 100644 --- a/apps/files_sharing/l10n/sk.js +++ b/apps/files_sharing/l10n/sk.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Sprístupnenie pomocou verejných odkazov je zakázané administrátorom", "Public upload disabled by the administrator" : "Verejné nahrávanie je zakázané administrátorom", "Public upload is only possible for publicly shared folders" : "Verejné nahrávanie je možné len do verejne sprístupnených priečinkov", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Zdieľanie %s odoslaním hesla cez Nextcloud Talk zlyhalo, pretože Nextcloud Talk nie je zapnutý", "Invalid date, date format must be YYYY-MM-DD" : "Neplatný dátum, formát musí byť v tvare YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Sprístupnenie %1$s zlyhalo, backend nepodporuje typ sprístupnenia %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Zdieľanie %s odoslaním hesla cez Nextcloud Talk zlyhalo, pretože Nextcloud Talk nie je zapnutý", "You cannot share to a Circle if the app is not enabled" : "Ak aplikácia nie je povolená, nemôžete ju zdieľať s Kruhom", "Please specify a valid circle" : "Zadajte platný kruh", "Sharing %s failed because the back end does not support room shares" : "Zdieľanie %s sa nepodarilo, pretože backend nepodporuje zdieľanie miestností", diff --git a/apps/files_sharing/l10n/sk.json b/apps/files_sharing/l10n/sk.json index 6565bcb7d80..15b7534aa7e 100644 --- a/apps/files_sharing/l10n/sk.json +++ b/apps/files_sharing/l10n/sk.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Sprístupnenie pomocou verejných odkazov je zakázané administrátorom", "Public upload disabled by the administrator" : "Verejné nahrávanie je zakázané administrátorom", "Public upload is only possible for publicly shared folders" : "Verejné nahrávanie je možné len do verejne sprístupnených priečinkov", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Zdieľanie %s odoslaním hesla cez Nextcloud Talk zlyhalo, pretože Nextcloud Talk nie je zapnutý", "Invalid date, date format must be YYYY-MM-DD" : "Neplatný dátum, formát musí byť v tvare YYYY-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Sprístupnenie %1$s zlyhalo, backend nepodporuje typ sprístupnenia %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Zdieľanie %s odoslaním hesla cez Nextcloud Talk zlyhalo, pretože Nextcloud Talk nie je zapnutý", "You cannot share to a Circle if the app is not enabled" : "Ak aplikácia nie je povolená, nemôžete ju zdieľať s Kruhom", "Please specify a valid circle" : "Zadajte platný kruh", "Sharing %s failed because the back end does not support room shares" : "Zdieľanie %s sa nepodarilo, pretože backend nepodporuje zdieľanie miestností", diff --git a/apps/files_sharing/l10n/sr.js b/apps/files_sharing/l10n/sr.js index 2d3ff556ee7..78524b05961 100644 --- a/apps/files_sharing/l10n/sr.js +++ b/apps/files_sharing/l10n/sr.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Администратор је забранио дељење јавном везом", "Public upload disabled by the administrator" : "Администратор је забранио отпремања са јавним приступом", "Public upload is only possible for publicly shared folders" : "Отпремања са јавним приступом су могућа само за јавно дељене фасцикле", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Дељење %s слањем лозинке преко Nextcloud Talk-а није успело пошто Nextcloud Talk није укључен", "Invalid date, date format must be YYYY-MM-DD" : "Неисправан датим, формат датума мора бити ГГГГ-ММ-ДД", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Дељење %1$s није успело зато што позадина не дозвољава дељење које је типа %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Дељење %s слањем лозинке преко Nextcloud Talk-а није успело пошто Nextcloud Talk није укључен", "You cannot share to a Circle if the app is not enabled" : "Не можете делити са Круговима ако та апликација није укључена", "Please specify a valid circle" : "Одаберите исправан круг", "Sharing %s failed because the back end does not support room shares" : "Није успело дељење %s зато што позадински мотор дељења не подржава дељења у соби", diff --git a/apps/files_sharing/l10n/sr.json b/apps/files_sharing/l10n/sr.json index 9eb7d45cf69..e163ef0e32f 100644 --- a/apps/files_sharing/l10n/sr.json +++ b/apps/files_sharing/l10n/sr.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Администратор је забранио дељење јавном везом", "Public upload disabled by the administrator" : "Администратор је забранио отпремања са јавним приступом", "Public upload is only possible for publicly shared folders" : "Отпремања са јавним приступом су могућа само за јавно дељене фасцикле", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Дељење %s слањем лозинке преко Nextcloud Talk-а није успело пошто Nextcloud Talk није укључен", "Invalid date, date format must be YYYY-MM-DD" : "Неисправан датим, формат датума мора бити ГГГГ-ММ-ДД", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Дељење %1$s није успело зато што позадина не дозвољава дељење које је типа %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Дељење %s слањем лозинке преко Nextcloud Talk-а није успело пошто Nextcloud Talk није укључен", "You cannot share to a Circle if the app is not enabled" : "Не можете делити са Круговима ако та апликација није укључена", "Please specify a valid circle" : "Одаберите исправан круг", "Sharing %s failed because the back end does not support room shares" : "Није успело дељење %s зато што позадински мотор дељења не подржава дељења у соби", diff --git a/apps/files_sharing/l10n/sv.js b/apps/files_sharing/l10n/sv.js index 47eb4771378..439ecb2509d 100644 --- a/apps/files_sharing/l10n/sv.js +++ b/apps/files_sharing/l10n/sv.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Offentlig delningslänk är avstängt", "Public upload disabled by the administrator" : "Offentlig uppladdning är avstängt", "Public upload is only possible for publicly shared folders" : "Offentlig uppladdning fungerar endast i offentligt delade mappar", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Dela %s och skicka lösenordet via Nextcloud Talk går inte eftersom Nextcloud Talk är inte aktiverad", "Invalid date, date format must be YYYY-MM-DD" : "Ogiltigt datum, måste anges: ÅÅÅÅ-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Delning %1$s misslyckades. Ej tillåtet med delningar från typ %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Dela %s och skicka lösenordet via Nextcloud Talk går inte eftersom Nextcloud Talk är inte aktiverad", "You cannot share to a Circle if the app is not enabled" : "Du kan inte dela till en cirkel om appen inte är aktiverad", "Please specify a valid circle" : "Vänligen ange en giltig cirkel", "Sharing %s failed because the back end does not support room shares" : "Dela %s misslyckades eftersom systemet inte stödjer rum-delningar", diff --git a/apps/files_sharing/l10n/sv.json b/apps/files_sharing/l10n/sv.json index a68cb493b17..ffccde59908 100644 --- a/apps/files_sharing/l10n/sv.json +++ b/apps/files_sharing/l10n/sv.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Offentlig delningslänk är avstängt", "Public upload disabled by the administrator" : "Offentlig uppladdning är avstängt", "Public upload is only possible for publicly shared folders" : "Offentlig uppladdning fungerar endast i offentligt delade mappar", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Dela %s och skicka lösenordet via Nextcloud Talk går inte eftersom Nextcloud Talk är inte aktiverad", "Invalid date, date format must be YYYY-MM-DD" : "Ogiltigt datum, måste anges: ÅÅÅÅ-MM-DD", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Delning %1$s misslyckades. Ej tillåtet med delningar från typ %2$s", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Dela %s och skicka lösenordet via Nextcloud Talk går inte eftersom Nextcloud Talk är inte aktiverad", "You cannot share to a Circle if the app is not enabled" : "Du kan inte dela till en cirkel om appen inte är aktiverad", "Please specify a valid circle" : "Vänligen ange en giltig cirkel", "Sharing %s failed because the back end does not support room shares" : "Dela %s misslyckades eftersom systemet inte stödjer rum-delningar", diff --git a/apps/files_sharing/l10n/tr.js b/apps/files_sharing/l10n/tr.js index 11f5d833fac..c0926ba1274 100644 --- a/apps/files_sharing/l10n/tr.js +++ b/apps/files_sharing/l10n/tr.js @@ -88,9 +88,9 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "Herkese açık bağlantı paylaşımı yönetici tarafından devre dışı bırakılmış", "Public upload disabled by the administrator" : "Herkese açık yükleme yönetici tarafından devre dışı bırakılmış", "Public upload is only possible for publicly shared folders" : "Herkese açık yükleme ancak herkese açık paylaşılmış klasörlere yapılabilir", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Nextcloud Talk etkinleştirilmemiş olduğundan %sNextcloud Talk ile parola gönderilerek paylaşılamadı", "Invalid date, date format must be YYYY-MM-DD" : "Tarih geçersiz. Tarih biçimi YYYY-AA-GG olmalıdır", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Yönetim bölümünden %2$s türündeki paylaşımlar yapılamadığından %1$s paylaşılamadı", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Nextcloud Talk etkinleştirilmemiş olduğundan %sNextcloud Talk ile parola gönderilerek paylaşılamadı", "You cannot share to a Circle if the app is not enabled" : "Uygulama etkinleştirilmemiş ise bir Çevre ile paylaşamazsınız", "Please specify a valid circle" : "Lütfen geçerli bir çevre belirtin", "Sharing %s failed because the back end does not support room shares" : "Arka uç oda paylaşımlarına izin vermediğinden %s paylaşılamadı", diff --git a/apps/files_sharing/l10n/tr.json b/apps/files_sharing/l10n/tr.json index dff28b90a41..55f6821339c 100644 --- a/apps/files_sharing/l10n/tr.json +++ b/apps/files_sharing/l10n/tr.json @@ -86,9 +86,9 @@ "Public link sharing is disabled by the administrator" : "Herkese açık bağlantı paylaşımı yönetici tarafından devre dışı bırakılmış", "Public upload disabled by the administrator" : "Herkese açık yükleme yönetici tarafından devre dışı bırakılmış", "Public upload is only possible for publicly shared folders" : "Herkese açık yükleme ancak herkese açık paylaşılmış klasörlere yapılabilir", + "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Nextcloud Talk etkinleştirilmemiş olduğundan %sNextcloud Talk ile parola gönderilerek paylaşılamadı", "Invalid date, date format must be YYYY-MM-DD" : "Tarih geçersiz. Tarih biçimi YYYY-AA-GG olmalıdır", "Sharing %1$s failed because the back end does not allow shares from type %2$s" : "Yönetim bölümünden %2$s türündeki paylaşımlar yapılamadığından %1$s paylaşılamadı", - "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "Nextcloud Talk etkinleştirilmemiş olduğundan %sNextcloud Talk ile parola gönderilerek paylaşılamadı", "You cannot share to a Circle if the app is not enabled" : "Uygulama etkinleştirilmemiş ise bir Çevre ile paylaşamazsınız", "Please specify a valid circle" : "Lütfen geçerli bir çevre belirtin", "Sharing %s failed because the back end does not support room shares" : "Arka uç oda paylaşımlarına izin vermediğinden %s paylaşılamadı", diff --git a/apps/files_sharing/l10n/zh_CN.js b/apps/files_sharing/l10n/zh_CN.js index dbed6a651ca..48119ecd7ad 100644 --- a/apps/files_sharing/l10n/zh_CN.js +++ b/apps/files_sharing/l10n/zh_CN.js @@ -87,8 +87,8 @@ OC.L10N.register( "Public link sharing is disabled by the administrator" : "公共链接共享已被管理员禁用", "Public upload disabled by the administrator" : "公共上传已被管理员禁用", "Public upload is only possible for publicly shared folders" : "公共上传仅适用于公共共享文件夹", - "Invalid date, date format must be YYYY-MM-DD" : "无效的日期,日期格式必须是 YYYY-MM-DD", "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "由于 Nextcloud Talk 没有启用, 所以通过 Nextcloud Talk 发送 %s 共享密码失败.", + "Invalid date, date format must be YYYY-MM-DD" : "无效的日期,日期格式必须是 YYYY-MM-DD", "You cannot share to a Circle if the app is not enabled" : "如果这个应用程序不可用,你不能共享到圈子", "Please specify a valid circle" : "请指明一个可用圈子", "Sharing %s failed because the back end does not support room shares" : "由于后端不支持房间共享, 所以共享 %s 失败.", diff --git a/apps/files_sharing/l10n/zh_CN.json b/apps/files_sharing/l10n/zh_CN.json index 47c506af8a1..8bd4c81b4de 100644 --- a/apps/files_sharing/l10n/zh_CN.json +++ b/apps/files_sharing/l10n/zh_CN.json @@ -85,8 +85,8 @@ "Public link sharing is disabled by the administrator" : "公共链接共享已被管理员禁用", "Public upload disabled by the administrator" : "公共上传已被管理员禁用", "Public upload is only possible for publicly shared folders" : "公共上传仅适用于公共共享文件夹", - "Invalid date, date format must be YYYY-MM-DD" : "无效的日期,日期格式必须是 YYYY-MM-DD", "Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled" : "由于 Nextcloud Talk 没有启用, 所以通过 Nextcloud Talk 发送 %s 共享密码失败.", + "Invalid date, date format must be YYYY-MM-DD" : "无效的日期,日期格式必须是 YYYY-MM-DD", "You cannot share to a Circle if the app is not enabled" : "如果这个应用程序不可用,你不能共享到圈子", "Please specify a valid circle" : "请指明一个可用圈子", "Sharing %s failed because the back end does not support room shares" : "由于后端不支持房间共享, 所以共享 %s 失败.", diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index ff19c35e2b5..42d0218de8c 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -160,6 +160,7 @@ class ShareAPIController extends OCSController { 'token' => null, 'uid_file_owner' => $share->getShareOwner(), 'note' => $share->getNote(), + 'label' => $share->getLabel(), 'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(), ]; @@ -211,6 +212,8 @@ class ShareAPIController extends OCSController { $result['share_with'] = $share->getPassword(); $result['share_with_displayname'] = $share->getPassword(); + $result['send_password_by_talk'] = $share->getSendPasswordByTalk(); + $result['token'] = $share->getToken(); $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); @@ -252,6 +255,7 @@ class ShareAPIController extends OCSController { $result['mail_send'] = $share->getMailSend() ? 1 : 0; + $result['hide_download'] = $share->getHideDownload() ? 1 : 0; return $result; } @@ -353,15 +357,17 @@ class ShareAPIController extends OCSController { * @param string $shareWith * @param string $publicUpload * @param string $password - * @param bool $sendPasswordByTalk + * @param string $sendPasswordByTalk * @param string $expireDate + * @param string $label * * @return DataResponse - * @throws OCSNotFoundException - * @throws OCSForbiddenException + * @throws NotFoundException * @throws OCSBadRequestException * @throws OCSException - * + * @throws OCSForbiddenException + * @throws OCSNotFoundException + * @throws \OCP\Files\InvalidPathException * @suppress PhanUndeclaredClassMethod */ public function createShare( @@ -372,7 +378,8 @@ class ShareAPIController extends OCSController { string $publicUpload = 'false', string $password = '', string $sendPasswordByTalk = null, - string $expireDate = '' + string $expireDate = '', + string $label = '' ): DataResponse { $share = $this->shareManager->newShare(); @@ -446,15 +453,6 @@ class ShareAPIController extends OCSController { throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator')); } - /* - * For now we only allow 1 link share. - * Return the existing link share if this is a duplicate - */ - $existingShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, false, 1, 0); - if (!empty($existingShares)) { - return new DataResponse($this->formatShare($existingShares[0])); - } - if ($publicUpload === 'true') { // Check if public upload is allowed if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { @@ -481,6 +479,19 @@ class ShareAPIController extends OCSController { $share->setPassword($password); } + + if (!empty($label)) { + $share->setLabel($label); + } + + if ($sendPasswordByTalk === 'true') { + if (!$this->appManager->isEnabledForUser('spreed')) { + throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()])); + } + + $share->setSendPasswordByTalk(true); + } + //Expire date if ($expireDate !== '') { try { @@ -745,6 +756,8 @@ class ShareAPIController extends OCSController { * @param string $publicUpload * @param string $expireDate * @param string $note + * @param string $label + * @param string $hideDownload * @return DataResponse * @throws LockedException * @throws NotFoundException @@ -759,7 +772,9 @@ class ShareAPIController extends OCSController { string $sendPasswordByTalk = null, string $publicUpload = null, string $expireDate = null, - string $note = null + string $note = null, + string $label = null, + string $hideDownload = null ): DataResponse { try { $share = $this->getShareById($id); @@ -773,7 +788,15 @@ class ShareAPIController extends OCSController { throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist')); } - if ($permissions === null && $password === null && $sendPasswordByTalk === null && $publicUpload === null && $expireDate === null && $note === null) { + if ($permissions === null && + $password === null && + $sendPasswordByTalk === null && + $publicUpload === null && + $expireDate === null && + $note === null && + $label === null && + $hideDownload === null + ) { throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given')); } @@ -786,6 +809,13 @@ class ShareAPIController extends OCSController { */ if ($share->getShareType() === Share::SHARE_TYPE_LINK) { + // Update hide download state + if ($hideDownload === 'true') { + $share->setHideDownload(true); + } else if ($hideDownload === 'false') { + $share->setHideDownload(false); + } + $newPermissions = null; if ($publicUpload === 'true') { $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE; @@ -850,6 +880,19 @@ class ShareAPIController extends OCSController { $share->setPassword($password); } + if ($label !== null) { + $share->setLabel($label); + } + + if ($sendPasswordByTalk === 'true') { + if (!$this->appManager->isEnabledForUser('spreed')) { + throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled')); + } + + $share->setSendPasswordByTalk(true); + } else if ($sendPasswordByTalk !== null) { + $share->setSendPasswordByTalk(false); + } } else { if ($permissions !== null) { $permissions = (int)$permissions; diff --git a/apps/files_sharing/lib/Controller/ShareController.php b/apps/files_sharing/lib/Controller/ShareController.php index 1e3cbb51028..1a92000a5f6 100644 --- a/apps/files_sharing/lib/Controller/ShareController.php +++ b/apps/files_sharing/lib/Controller/ShareController.php @@ -321,6 +321,7 @@ class ShareController extends AuthPublicShareController { $shareTmpl['dir'] = ''; $shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize(); $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize()); + $shareTmpl['hideDownload'] = $share->getHideDownload(); // Show file list $hideFileList = false; @@ -444,12 +445,14 @@ class ShareController extends AuthPublicShareController { $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl); $response->setHeaderTitle($shareTmpl['filename']); $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']])); - $response->setHeaderActions([ - new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0), - new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']), - new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']), - new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']), - ]); + if (!$share->getHideDownload()) { + $response->setHeaderActions([ + new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0), + new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']), + new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']), + new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']), + ]); + } $response->setContentSecurityPolicy($csp); diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index da80f8d1377..4487e63f2de 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -11,13 +11,16 @@ <input type="hidden" id="filesApp" name="filesApp" value="1"> <input type="hidden" id="isPublic" name="isPublic" value="1"> <input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir"> -<input type="hidden" name="downloadURL" value="<?php p($_['downloadURL']) ?>" id="downloadURL"> +<?php if (!$_['hideDownload']): ?> + <input type="hidden" name="downloadURL" value="<?php p($_['downloadURL']) ?>" id="downloadURL"> +<?php endif; ?> <input type="hidden" name="previewURL" value="<?php p($_['previewURL']) ?>" id="previewURL"> <input type="hidden" name="sharingToken" value="<?php p($_['sharingToken']) ?>" id="sharingToken"> <input type="hidden" name="filename" value="<?php p($_['filename']) ?>" id="filename"> <input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype"> <input type="hidden" name="previewSupported" value="<?php p($_['previewSupported'] ? 'true' : 'false'); ?>" id="previewSupported"> <input type="hidden" name="mimetypeIcon" value="<?php p(\OC::$server->getMimeTypeDetector()->mimeTypeIcon($_['mimetype'])); ?>" id="mimetypeIcon"> +<input type="hidden" name="hideDownload" value="<?php p($_['hideDownload'] ? 'true' : 'false'); ?>" id="hideDownload"> <?php $upload_max_filesize = OC::$server->getIniWrapper()->getBytes('upload_max_filesize'); $post_max_size = OC::$server->getIniWrapper()->getBytes('post_max_size'); @@ -58,7 +61,7 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); <!-- Preview frame is filled via JS to support SVG images for modern browsers --> <div id="imgframe"></div> <?php endif; ?> - <?php if ($_['previewURL'] === $_['downloadURL']): ?> + <?php if ($_['previewURL'] === $_['downloadURL'] && !$_['hideDownload']): ?> <div class="directDownload"> <a href="<?php p($_['downloadURL']); ?>" id="downloadFile" class="button"> <span class="icon icon-download"></span> @@ -97,4 +100,4 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); data-url="<?php p(\OC::$server->getURLGenerator()->linkTo('files', 'ajax/upload.php')); ?>" /> </div> <?php endif; ?> -</div>
\ No newline at end of file +</div> diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 15c4071bc46..efc252d49d7 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -253,7 +253,7 @@ class ShareAPIControllerTest extends TestCase { public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions, $shareTime, $expiration, $parent, $target, $mail_send, $note = '', $token=null, - $password=null) { + $password=null, $label = '') { $share = $this->getMockBuilder(IShare::class)->getMock(); $share->method('getId')->willReturn($id); $share->method('getShareType')->willReturn($shareType); @@ -263,6 +263,7 @@ class ShareAPIControllerTest extends TestCase { $share->method('getNode')->willReturn($path); $share->method('getPermissions')->willReturn($permissions); $share->method('getNote')->willReturn($note); + $share->method('getLabel')->willReturn($label); $time = new \DateTime(); $time->setTimestamp($shareTime); $share->method('getShareTime')->willReturn($time); @@ -351,8 +352,10 @@ class ShareAPIControllerTest extends TestCase { 'mail_send' => 0, 'uid_file_owner' => 'ownerId', 'note' => 'personal note', + 'label' => '', 'displayname_file_owner' => 'ownerDisplay', 'mimetype' => 'myMimeType', + 'hide_download' => 0, ]; $data[] = [$share, $expected]; @@ -395,8 +398,10 @@ class ShareAPIControllerTest extends TestCase { 'mail_send' => 0, 'uid_file_owner' => 'ownerId', 'note' => 'personal note', + 'label' => '', 'displayname_file_owner' => 'ownerDisplay', 'mimetype' => 'myFolderMimeType', + 'hide_download' => 0, ]; $data[] = [$share, $expected]; @@ -417,13 +422,15 @@ class ShareAPIControllerTest extends TestCase { 0, 'personal note', 'token', - 'password' + 'password', + 'first link share' ); $expected = [ 'id' => 101, 'share_type' => \OCP\Share::SHARE_TYPE_LINK, 'share_with' => 'password', 'share_with_displayname' => 'password', + 'send_password_by_talk' => false, 'uid_owner' => 'initiatorId', 'displayname_owner' => 'initiatorDisplay', 'item_type' => 'folder', @@ -443,8 +450,10 @@ class ShareAPIControllerTest extends TestCase { 'url' => 'url', 'uid_file_owner' => 'ownerId', 'note' => 'personal note', + 'label' => 'first link share', 'displayname_file_owner' => 'ownerDisplay', 'mimetype' => 'myFolderMimeType', + 'hide_download' => 0, ]; $data[] = [$share, $expected]; @@ -1127,6 +1136,71 @@ class ShareAPIControllerTest extends TestCase { $this->assertEquals($expected->getData(), $result->getData()); } + public function testCreateShareLinkSendPasswordByTalk() { + $ocs = $this->mockFormatShare(); + + $path = $this->getMockBuilder(Folder::class)->getMock(); + $storage = $this->getMockBuilder(Storage::class)->getMock(); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser)->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true); + + $this->shareManager->expects($this->once())->method('createShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && + $share->getPermissions() === \OCP\Constants::PERMISSION_READ && + $share->getSharedBy() === 'currentUser' && + $share->getPassword() === 'password' && + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() === null; + }) + )->will($this->returnArgument(0)); + + $expected = new DataResponse([]); + $result = $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_LINK, null, 'false', 'password', 'true', ''); + + $this->assertInstanceOf(get_class($expected), $result); + $this->assertEquals($expected->getData(), $result->getData()); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSForbiddenException + * @expectedExceptionMessage Sharing valid-path sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled + */ + public function testCreateShareLinkSendPasswordByTalkWithTalkDisabled() { + $ocs = $this->mockFormatShare(); + + $path = $this->getMockBuilder(Folder::class)->getMock(); + $storage = $this->getMockBuilder(Storage::class)->getMock(); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $path->method('getPath')->willReturn('valid-path'); + $this->rootFolder->method('getUserFolder')->with($this->currentUser)->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false); + + $this->shareManager->expects($this->never())->method('createShare'); + + $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_LINK, null, 'false', 'password', 'true', ''); + } + public function testCreateShareValidExpireDate() { $ocs = $this->mockFormatShare(); @@ -1504,6 +1578,9 @@ class ShareAPIControllerTest extends TestCase { ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') ->setExpirationDate(new \DateTime()) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) ->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setNode($node); @@ -1517,7 +1594,12 @@ class ShareAPIControllerTest extends TestCase { $this->callback(function (\OCP\Share\IShare $share) { return $share->getPermissions() === \OCP\Constants::PERMISSION_READ && $share->getPassword() === null && - $share->getExpirationDate() === null; + $share->getExpirationDate() === null && + // Once set a note or a label are never back to null, only to an + // empty string. + $share->getNote() === '' && + $share->getLabel() === '' && + $share->getHideDownload() === false; }) )->will($this->returnArgument(0)); @@ -1525,7 +1607,7 @@ class ShareAPIControllerTest extends TestCase { ->willReturn([]); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, null, '', null, 'false', ''); + $result = $ocs->updateShare(42, null, '', null, 'false', '', '', '', 'false'); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -1552,7 +1634,10 @@ class ShareAPIControllerTest extends TestCase { return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && $share->getPassword() === 'password' && - $share->getExpirationDate() == $date; + $share->getExpirationDate() == $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; }) )->will($this->returnArgument(0)); @@ -1560,7 +1645,7 @@ class ShareAPIControllerTest extends TestCase { ->willReturn([]); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-01'); + $result = $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-01', 'note', 'label', 'true'); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -1692,7 +1777,11 @@ class ShareAPIControllerTest extends TestCase { ->setSharedBy($this->currentUser) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') + ->setSendPasswordByTalk(true) ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) ->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setNode($node); @@ -1706,12 +1795,194 @@ class ShareAPIControllerTest extends TestCase { $this->callback(function (\OCP\Share\IShare $share) use ($date) { return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && $share->getPassword() === 'newpassword' && - $share->getExpirationDate() === $date; + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; }) )->will($this->returnArgument(0)); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, null, 'newpassword', null, null, null); + $result = $ocs->updateShare(42, null, 'newpassword', null, null, null, null, null, null); + + $this->assertInstanceOf(get_class($expected), $result); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareSendPasswordByTalkDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + $node = $this->getMockBuilder(File::class)->getMock(); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setSendPasswordByTalk(false) + ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($date) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getPassword() === 'password' && + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; + }) + )->will($this->returnArgument(0)); + + $expected = new DataResponse([]); + $result = $ocs->updateShare(42, null, null, 'true', null, null, null, null, null); + + $this->assertInstanceOf(get_class($expected), $result); + $this->assertEquals($expected->getData(), $result->getData()); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSForbiddenException + * @expectedExceptionMessage Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled + */ + public function testUpdateLinkShareSendPasswordByTalkWithTalkDisabledDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + $node = $this->getMockBuilder(File::class)->getMock(); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setSendPasswordByTalk(false) + ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false); + + $this->shareManager->expects($this->never())->method('updateShare'); + + $ocs->updateShare(42, null, null, 'true', null, null, null, null, null); + } + + public function testUpdateLinkShareDoNotSendPasswordByTalkDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + $node = $this->getMockBuilder(File::class)->getMock(); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setSendPasswordByTalk(true) + ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($date) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getPassword() === 'password' && + $share->getSendPasswordByTalk() === false && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; + }) + )->will($this->returnArgument(0)); + + $expected = new DataResponse([]); + $result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null); + + $this->assertInstanceOf(get_class($expected), $result); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareDoNotSendPasswordByTalkWithTalkDisabledDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + $node = $this->getMockBuilder(File::class)->getMock(); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setSendPasswordByTalk(true) + ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($date) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getPassword() === 'password' && + $share->getSendPasswordByTalk() === false && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; + }) + )->will($this->returnArgument(0)); + + $expected = new DataResponse([]); + $result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -1726,7 +1997,11 @@ class ShareAPIControllerTest extends TestCase { ->setSharedBy($this->currentUser) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') + ->setSendPasswordByTalk(true) ->setExpirationDate(new \DateTime()) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) ->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setNode($node); @@ -1743,12 +2018,16 @@ class ShareAPIControllerTest extends TestCase { return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && $share->getPassword() === 'password' && - $share->getExpirationDate() == $date; + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() == $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; }) )->will($this->returnArgument(0)); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, null, null, null, null, '2010-12-23'); + $result = $ocs->updateShare(42, null, null, null, null, '2010-12-23', null, null, null); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -1766,7 +2045,11 @@ class ShareAPIControllerTest extends TestCase { ->setSharedBy($this->currentUser) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') + ->setSendPasswordByTalk(true) ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) ->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setNode($folder); @@ -1777,7 +2060,11 @@ class ShareAPIControllerTest extends TestCase { $this->callback(function (\OCP\Share\IShare $share) use ($date) { return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && $share->getPassword() === 'password' && - $share->getExpirationDate() === $date; + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; }) )->will($this->returnArgument(0)); @@ -1785,7 +2072,7 @@ class ShareAPIControllerTest extends TestCase { ->willReturn([]); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, null, null, null, 'true', null); + $result = $ocs->updateShare(42, null, null, null, 'true', null, null, null, null); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -1803,7 +2090,11 @@ class ShareAPIControllerTest extends TestCase { ->setSharedBy($this->currentUser) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') + ->setSendPasswordByTalk(true) ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) ->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setNode($folder); @@ -1814,14 +2105,18 @@ class ShareAPIControllerTest extends TestCase { $this->callback(function (\OCP\Share\IShare $share) use ($date) { return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && $share->getPassword() === 'password' && - $share->getExpirationDate() === $date; + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; }) )->will($this->returnArgument(0)); $this->shareManager->method('getSharedWith')->willReturn([]); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, 7, null, null, null, null); + $result = $ocs->updateShare(42, 7, null, null, null, null, null, null, null); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -1839,7 +2134,11 @@ class ShareAPIControllerTest extends TestCase { ->setSharedBy($this->currentUser) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') + ->setSendPasswordByTalk(true) ->setExpirationDate($date) + ->setNote('note') + ->setLabel('label') + ->setHideDownload(true) ->setPermissions(\OCP\Constants::PERMISSION_READ) ->setNode($folder); @@ -1850,14 +2149,18 @@ class ShareAPIControllerTest extends TestCase { $this->callback(function (\OCP\Share\IShare $share) use ($date) { return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && $share->getPassword() === 'password' && - $share->getExpirationDate() === $date; + $share->getSendPasswordByTalk() === true && + $share->getExpirationDate() === $date && + $share->getNote() === 'note' && + $share->getLabel() === 'label' && + $share->getHideDownload() === true; }) )->will($this->returnArgument(0)); $this->shareManager->method('getSharedWith')->willReturn([]); $expected = new DataResponse([]); - $result = $ocs->updateShare(42, 31, null, null, null, null); + $result = $ocs->updateShare(42, 31, null, null, null, null, null, null, null); $this->assertInstanceOf(get_class($expected), $result); $this->assertEquals($expected->getData(), $result->getData()); @@ -2173,8 +2476,10 @@ class ShareAPIControllerTest extends TestCase { 'share_with' => 'recipient', 'share_with_displayname' => 'recipient', 'note' => 'personal note', + 'label' => null, 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, ], $share, [], false ]; // User backend up @@ -2192,6 +2497,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'ownerDN', 'note' => 'personal note', + 'label' => null, 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -2204,6 +2510,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'recipientDN', 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, ], $share, [ ['owner', $owner], ['initiator', $initiator], @@ -2237,6 +2544,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', + 'label' => null, 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -2249,6 +2557,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'recipient', 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2280,6 +2589,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', + 'label' => null, 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -2292,6 +2602,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'recipientGroupDisplayName', 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2321,6 +2632,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', + 'label' => null, 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -2333,6 +2645,55 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'recipientGroup2', 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, + ], $share, [], false + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setPassword('mypassword') + ->setExpirationDate(new \DateTime('2001-01-02T00:00:00')) + ->setToken('myToken') + ->setNote('personal note') + ->setLabel('new link share') + ->setId(42); + + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_LINK, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => '2001-01-02 00:00:00', + 'token' => 'myToken', + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'note' => 'personal note', + 'label' => 'new link share', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'mypassword', + 'share_with_displayname' => 'mypassword', + 'send_password_by_talk' => false, + 'mail_send' => 0, + 'url' => 'myLink', + 'mimetype' => 'myMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2345,9 +2706,11 @@ class ShareAPIControllerTest extends TestCase { ->setShareTime(new \DateTime('2000-01-01T00:01:02')) ->setTarget('myTarget') ->setPassword('mypassword') + ->setSendPasswordByTalk(true) ->setExpirationDate(new \DateTime('2001-01-02T00:00:00')) ->setToken('myToken') ->setNote('personal note') + ->setLabel('new link share') ->setId(42); $result[] = [ @@ -2364,6 +2727,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', + 'label' => 'new link share', 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -2374,9 +2738,11 @@ class ShareAPIControllerTest extends TestCase { 'file_target' => 'myTarget', 'share_with' => 'mypassword', 'share_with_displayname' => 'mypassword', + 'send_password_by_talk' => true, 'mail_send' => 0, 'url' => 'myLink', 'mimetype' => 'myMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2406,6 +2772,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', + 'label' => null, 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -2418,6 +2785,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'foobar', 'mail_send' => 0, 'mimetype' => 'myFolderMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2449,6 +2817,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', + 'label' => null, 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -2462,6 +2831,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_avatar' => 'path/to/the/avatar', 'mail_send' => 0, 'mimetype' => 'myFolderMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2491,6 +2861,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', + 'label' => null, 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -2504,6 +2875,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_avatar' => '', 'mail_send' => 0, 'mimetype' => 'myFolderMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2533,6 +2905,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', + 'label' => null, 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -2546,6 +2919,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_avatar' => '', 'mail_send' => 0, 'mimetype' => 'myFolderMimeType', + 'hide_download' => 0, ], $share, [], false ]; @@ -2590,6 +2964,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', + 'label' => null, 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -2603,7 +2978,8 @@ class ShareAPIControllerTest extends TestCase { 'mail_send' => 0, 'mimetype' => 'myFolderMimeType', 'password' => 'password', - 'send_password_by_talk' => false + 'send_password_by_talk' => false, + 'hide_download' => 0, ], $share, [], false ]; @@ -2634,6 +3010,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', + 'label' => null, 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -2647,7 +3024,8 @@ class ShareAPIControllerTest extends TestCase { 'mail_send' => 0, 'mimetype' => 'myFolderMimeType', 'password' => 'password', - 'send_password_by_talk' => true + 'send_password_by_talk' => true, + 'hide_download' => 0, ], $share, [], false ]; @@ -2787,6 +3165,8 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => '', 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, + 'label' => '', ], $share, false, [] ]; @@ -2828,6 +3208,8 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'recipientRoomName', 'mail_send' => 0, 'mimetype' => 'myMimeType', + 'hide_download' => 0, + 'label' => '', ], $share, true, [ 'share_with_displayname' => 'recipientRoomName' ] diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php index a01560d0288..c5306cbc0ce 100644 --- a/apps/files_sharing/tests/Controller/ShareControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php @@ -287,7 +287,8 @@ class ShareControllerTest extends \Test\TestCase { 'shareUrl' => null, 'previewImage' => null, 'previewURL' => 'downloadURL', - 'note' => $note + 'note' => $note, + 'hideDownload' => false ); $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy(); @@ -306,6 +307,120 @@ class ShareControllerTest extends \Test\TestCase { $this->assertEquals($expectedResponse, $response); } + public function testShowShareHideDownload() { + $note = 'personal note'; + + $this->shareController->setToken('token'); + + $owner = $this->getMockBuilder(IUser::class)->getMock(); + $owner->method('getDisplayName')->willReturn('ownerDisplay'); + $owner->method('getUID')->willReturn('ownerUID'); + + $file = $this->getMockBuilder('OCP\Files\File')->getMock(); + $file->method('getName')->willReturn('file1.txt'); + $file->method('getMimetype')->willReturn('text/plain'); + $file->method('getSize')->willReturn(33); + $file->method('isReadable')->willReturn(true); + $file->method('isShareable')->willReturn(true); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(42); + $share->setPassword('password') + ->setShareOwner('ownerUID') + ->setNode($file) + ->setNote($note) + ->setTarget('/file1.txt') + ->setHideDownload(true); + + $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); + $this->session->method('get')->with('public_link_authenticated')->willReturn('42'); + + // Even if downloads are disabled the "downloadURL" parameter is + // provided to the template, as it is needed to preview audio and GIF + // files. + $this->urlGenerator->expects($this->at(0)) + ->method('linkToRouteAbsolute') + ->with('files_sharing.sharecontroller.downloadShare', ['token' => 'token']) + ->willReturn('downloadURL'); + + $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true); + + $this->config->method('getSystemValue') + ->willReturnMap( + [ + ['max_filesize_animated_gifs_public_sharing', 10, 10], + ['enable_previews', true, true], + ['preview_max_x', 1024, 1024], + ['preview_max_y', 1024, 1024], + ] + ); + $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); + $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'shareapi_public_link_disclaimertext', null) + ->willReturn('My disclaimer text'); + + $this->userManager->method('get')->with('ownerUID')->willReturn($owner); + + $this->eventDispatcher->expects($this->once()) + ->method('dispatch') + ->with('OCA\Files_Sharing::loadAdditionalScripts'); + + $this->l10n->expects($this->any()) + ->method('t') + ->will($this->returnCallback(function($text, $parameters) { + return vsprintf($text, $parameters); + })); + + $response = $this->shareController->showShare(); + $sharedTmplParams = array( + 'displayName' => 'ownerDisplay', + 'owner' => 'ownerUID', + 'filename' => 'file1.txt', + 'directory_path' => '/file1.txt', + 'mimetype' => 'text/plain', + 'dirToken' => 'token', + 'sharingToken' => 'token', + 'server2serversharing' => true, + 'protected' => 'true', + 'dir' => '', + 'downloadURL' => 'downloadURL', + 'fileSize' => '33 B', + 'nonHumanFileSize' => 33, + 'maxSizeAnimateGif' => 10, + 'previewSupported' => true, + 'previewEnabled' => true, + 'previewMaxX' => 1024, + 'previewMaxY' => 1024, + 'hideFileList' => false, + 'shareOwner' => 'ownerDisplay', + 'disclaimer' => 'My disclaimer text', + 'shareUrl' => null, + 'previewImage' => null, + 'previewURL' => 'downloadURL', + 'note' => $note, + 'hideDownload' => true + ); + + $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy(); + $csp->addAllowedFrameDomain('\'self\''); + $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams); + $expectedResponse->setContentSecurityPolicy($csp); + $expectedResponse->setHeaderTitle($sharedTmplParams['filename']); + $expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['displayName']); + $expectedResponse->setHeaderActions([]); + + $this->assertEquals($expectedResponse, $response); + } + /** * @expectedException \OCP\Files\NotFoundException */ diff --git a/apps/files_trashbin/tests/CapabilitiesTest.php b/apps/files_trashbin/tests/CapabilitiesTest.php new file mode 100644 index 00000000000..2a3e89bf414 --- /dev/null +++ b/apps/files_trashbin/tests/CapabilitiesTest.php @@ -0,0 +1,44 @@ +<?php +/** + * @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\Tests; + +use OCA\Files_Trashbin\Capabilities; +use Test\TestCase; + +class CapabilitiesTest extends TestCase { + + /** @var Capabilities */ + private $capabilities; + + public function setUp() { + parent::setUp(); + $this->capabilities = new Capabilities(); + } + + public function testGetCapabilities() { + $capabilities = [ + 'files' => [ + 'undelete' => true + ] + ]; + + $this->assertSame($capabilities, $this->capabilities->getCapabilities()); + } +}
\ No newline at end of file diff --git a/apps/files_versions/appinfo/info.xml b/apps/files_versions/appinfo/info.xml index d2f873edb07..6d1b3085f80 100644 --- a/apps/files_versions/appinfo/info.xml +++ b/apps/files_versions/appinfo/info.xml @@ -41,4 +41,8 @@ <collection>OCA\Files_Versions\Sabre\RootCollection</collection> </collections> </sabre> + + <versions> + <backend for="OCP\Files\Storage\IStorage">OCA\Files_Versions\Versions\LegacyVersionsBackend</backend> + </versions> </info> diff --git a/apps/files_versions/composer/composer/autoload_classmap.php b/apps/files_versions/composer/composer/autoload_classmap.php index 4bb112b4f11..1283e533914 100644 --- a/apps/files_versions/composer/composer/autoload_classmap.php +++ b/apps/files_versions/composer/composer/autoload_classmap.php @@ -23,4 +23,11 @@ return array( 'OCA\\Files_Versions\\Sabre\\VersionHome' => $baseDir . '/../lib/Sabre/VersionHome.php', 'OCA\\Files_Versions\\Sabre\\VersionRoot' => $baseDir . '/../lib/Sabre/VersionRoot.php', 'OCA\\Files_Versions\\Storage' => $baseDir . '/../lib/Storage.php', + 'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => $baseDir . '/../lib/Versions/BackendNotFoundException.php', + 'OCA\\Files_Versions\\Versions\\IVersion' => $baseDir . '/../lib/Versions/IVersion.php', + 'OCA\\Files_Versions\\Versions\\IVersionBackend' => $baseDir . '/../lib/Versions/IVersionBackend.php', + 'OCA\\Files_Versions\\Versions\\IVersionManager' => $baseDir . '/../lib/Versions/IVersionManager.php', + 'OCA\\Files_Versions\\Versions\\LegacyVersionsBackend' => $baseDir . '/../lib/Versions/LegacyVersionsBackend.php', + 'OCA\\Files_Versions\\Versions\\Version' => $baseDir . '/../lib/Versions/Version.php', + 'OCA\\Files_Versions\\Versions\\VersionManager' => $baseDir . '/../lib/Versions/VersionManager.php', ); diff --git a/apps/files_versions/composer/composer/autoload_static.php b/apps/files_versions/composer/composer/autoload_static.php index 29bc592b41c..6a6b753c2e5 100644 --- a/apps/files_versions/composer/composer/autoload_static.php +++ b/apps/files_versions/composer/composer/autoload_static.php @@ -38,6 +38,13 @@ class ComposerStaticInitFiles_Versions 'OCA\\Files_Versions\\Sabre\\VersionHome' => __DIR__ . '/..' . '/../lib/Sabre/VersionHome.php', 'OCA\\Files_Versions\\Sabre\\VersionRoot' => __DIR__ . '/..' . '/../lib/Sabre/VersionRoot.php', 'OCA\\Files_Versions\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php', + 'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => __DIR__ . '/..' . '/../lib/Versions/BackendNotFoundException.php', + 'OCA\\Files_Versions\\Versions\\IVersion' => __DIR__ . '/..' . '/../lib/Versions/IVersion.php', + 'OCA\\Files_Versions\\Versions\\IVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IVersionBackend.php', + 'OCA\\Files_Versions\\Versions\\IVersionManager' => __DIR__ . '/..' . '/../lib/Versions/IVersionManager.php', + 'OCA\\Files_Versions\\Versions\\LegacyVersionsBackend' => __DIR__ . '/..' . '/../lib/Versions/LegacyVersionsBackend.php', + 'OCA\\Files_Versions\\Versions\\Version' => __DIR__ . '/..' . '/../lib/Versions/Version.php', + 'OCA\\Files_Versions\\Versions\\VersionManager' => __DIR__ . '/..' . '/../lib/Versions/VersionManager.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/apps/files_versions/js/versionstabview.js b/apps/files_versions/js/versionstabview.js index 61309a30d50..213ee1ae83c 100644 --- a/apps/files_versions/js/versionstabview.js +++ b/apps/files_versions/js/versionstabview.js @@ -38,6 +38,10 @@ return t('files_versions', 'Versions'); }, + getIcon: function() { + return 'icon-history'; + }, + nextPage: function() { if (this._loading) { return; diff --git a/apps/files_versions/l10n/es.js b/apps/files_versions/l10n/es.js index 9a18c7a7abd..13e46f592ba 100644 --- a/apps/files_versions/l10n/es.js +++ b/apps/files_versions/l10n/es.js @@ -5,12 +5,12 @@ OC.L10N.register( "Failed to revert {file} to revision {timestamp}." : "No se ha podido restaurar {file} a versión {timestamp}.", "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Restore" : "Recuperar", - "No other versions available" : "No hay otras versiones disponibles", + "No other versions available" : "No hay más versiones disponibles", "This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian.", - "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\n\nAdemás de la expiración de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.", + "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\n\n\t\tAdemás de la caducidad de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.", "Could not revert: %s" : "No se puede restaurar: %s", "No earlier versions available" : "No hay versiones previas disponibles", "More versions …" : "Más versiones ...", - "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\nIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.Además de la expiración de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones." + "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\nIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\nAdemás de la caducidad de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones." }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_versions/l10n/es.json b/apps/files_versions/l10n/es.json index 347002f6d19..667eec5a9a2 100644 --- a/apps/files_versions/l10n/es.json +++ b/apps/files_versions/l10n/es.json @@ -3,12 +3,12 @@ "Failed to revert {file} to revision {timestamp}." : "No se ha podido restaurar {file} a versión {timestamp}.", "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Restore" : "Recuperar", - "No other versions available" : "No hay otras versiones disponibles", + "No other versions available" : "No hay más versiones disponibles", "This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian.", - "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\n\nAdemás de la expiración de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.", + "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\n\n\t\tAdemás de la caducidad de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.", "Could not revert: %s" : "No se puede restaurar: %s", "No earlier versions available" : "No hay versiones previas disponibles", "More versions …" : "Más versiones ...", - "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\nIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.Además de la expiración de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones." + "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\nIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\nAdemás de la caducidad de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones." },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php index 340b5ab5cbd..935556221fa 100644 --- a/apps/files_versions/lib/AppInfo/Application.php +++ b/apps/files_versions/lib/AppInfo/Application.php @@ -24,9 +24,10 @@ namespace OCA\Files_Versions\AppInfo; use OCA\DAV\Connector\Sabre\Principal; +use OCA\Files_Versions\Versions\IVersionManager; +use OCA\Files_Versions\Versions\VersionManager; use OCP\AppFramework\App; -use OCA\Files_Versions\Expiration; -use OCP\AppFramework\Utility\ITimeFactory; +use OCP\AppFramework\IAppContainer; use OCA\Files_Versions\Capabilities; class Application extends App { @@ -43,14 +44,45 @@ class Application extends App { /* * Register $principalBackend for the DAV collection */ - $container->registerService('principalBackend', function () { + $container->registerService('principalBackend', function (IAppContainer $c) { + $server = $c->getServer(); return new Principal( - \OC::$server->getUserManager(), - \OC::$server->getGroupManager(), - \OC::$server->getShareManager(), - \OC::$server->getUserSession(), - \OC::$server->getConfig() + $server->getUserManager(), + $server->getGroupManager(), + $server->getShareManager(), + $server->getUserSession(), + $server->getConfig() ); }); + + $container->registerService(IVersionManager::class, function(IAppContainer $c) { + return new VersionManager(); + }); + + $this->registerVersionBackends(); + } + + public function registerVersionBackends() { + $server = $this->getContainer()->getServer(); + $logger = $server->getLogger(); + $appManager = $server->getAppManager(); + /** @var IVersionManager $versionManager */ + $versionManager = $this->getContainer()->getServer()->query(IVersionManager::class); + foreach($appManager->getInstalledApps() as $app) { + $appInfo = $appManager->getAppInfo($app); + if (isset($appInfo['versions'])) { + $backends = $appInfo['versions']; + foreach($backends as $backend) { + $class = $backend['@value']; + $for = $backend['@attributes']['for']; + try { + $backendObject = $server->query($class); + $versionManager->registerBackend($for, $backendObject); + } catch (\Exception $e) { + $logger->logException($e); + } + } + } + } } } diff --git a/apps/files_versions/lib/Controller/PreviewController.php b/apps/files_versions/lib/Controller/PreviewController.php index b8bf464fb3f..f41250a8971 100644 --- a/apps/files_versions/lib/Controller/PreviewController.php +++ b/apps/files_versions/lib/Controller/PreviewController.php @@ -21,45 +21,53 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\Files_Versions\Controller; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\FileDisplayResponse; -use OCP\Files\File; -use OCP\Files\Folder; use OCP\Files\IMimeTypeDetector; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\IPreview; use OCP\IRequest; +use OCP\IUserSession; class PreviewController extends Controller { /** @var IRootFolder */ private $rootFolder; - /** @var string */ - private $userId; + /** @var IUserSession */ + private $userSession; /** @var IMimeTypeDetector */ private $mimeTypeDetector; + /** @var IVersionManager */ + private $versionManager; + /** @var IPreview */ private $previewManager; - public function __construct($appName, - IRequest $request, - IRootFolder $rootFolder, - $userId, - IMimeTypeDetector $mimeTypeDetector, - IPreview $previewManager) { + public function __construct( + $appName, + IRequest $request, + IRootFolder $rootFolder, + IUserSession $userSession, + IMimeTypeDetector $mimeTypeDetector, + IVersionManager $versionManager, + IPreview $previewManager + ) { parent::__construct($appName, $request); $this->rootFolder = $rootFolder; - $this->userId = $userId; + $this->userSession = $userSession; $this->mimeTypeDetector = $mimeTypeDetector; + $this->versionManager = $versionManager; $this->previewManager = $previewManager; } @@ -79,20 +87,17 @@ class PreviewController extends Controller { $y = 44, $version = '' ) { - if($file === '' || $version === '' || $x === 0 || $y === 0) { + if ($file === '' || $version === '' || $x === 0 || $y === 0) { return new DataResponse([], Http::STATUS_BAD_REQUEST); } try { - $userFolder = $this->rootFolder->getUserFolder($this->userId); - /** @var Folder $versionFolder */ - $versionFolder = $userFolder->getParent()->get('files_versions'); - $mimeType = $this->mimeTypeDetector->detectPath($file); - $file = $versionFolder->get($file.'.v'.$version); - - /** @var File $file */ - $f = $this->previewManager->getPreview($file, $x, $y, true, IPreview::MODE_FILL, $mimeType); - return new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]); + $user = $this->userSession->getUser(); + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $file = $userFolder->get($file); + $versionFile = $this->versionManager->getVersionFile($user, $file, (int)$version); + $preview = $this->previewManager->getPreview($versionFile, $x, $y, true, IPreview::MODE_FILL, $versionFile->getMimetype()); + return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]); } catch (NotFoundException $e) { return new DataResponse([], Http::STATUS_NOT_FOUND); } catch (\InvalidArgumentException $e) { diff --git a/apps/files_versions/lib/Sabre/RestoreFolder.php b/apps/files_versions/lib/Sabre/RestoreFolder.php index c398d02692b..c8504646bad 100644 --- a/apps/files_versions/lib/Sabre/RestoreFolder.php +++ b/apps/files_versions/lib/Sabre/RestoreFolder.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace OCA\Files_Versions\Sabre; +use OCP\IUser; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\ICollection; use Sabre\DAV\IMoveTarget; @@ -31,14 +32,6 @@ 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(); } @@ -80,7 +73,8 @@ class RestoreFolder implements ICollection, IMoveTarget { return false; } - return $sourceNode->rollBack(); + $sourceNode->rollBack(); + return true; } } diff --git a/apps/files_versions/lib/Sabre/RootCollection.php b/apps/files_versions/lib/Sabre/RootCollection.php index ca5979573b5..504c3362505 100644 --- a/apps/files_versions/lib/Sabre/RootCollection.php +++ b/apps/files_versions/lib/Sabre/RootCollection.php @@ -20,10 +20,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\Files_Versions\Sabre; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\Files\IRootFolder; use OCP\IConfig; +use OCP\IUserManager; use Sabre\DAV\INode; use Sabre\DAVACL\AbstractPrincipalCollection; use Sabre\DAVACL\PrincipalBackend; @@ -33,12 +36,24 @@ class RootCollection extends AbstractPrincipalCollection { /** @var IRootFolder */ private $rootFolder; - public function __construct(PrincipalBackend\BackendInterface $principalBackend, - IRootFolder $rootFolder, - IConfig $config) { + /** @var IUserManager */ + private $userManager; + + /** @var IVersionManager */ + private $versionManager; + + public function __construct( + PrincipalBackend\BackendInterface $principalBackend, + IRootFolder $rootFolder, + IConfig $config, + IUserManager $userManager, + IVersionManager $versionManager + ) { parent::__construct($principalBackend, 'principals/users'); $this->rootFolder = $rootFolder; + $this->userManager = $userManager; + $this->versionManager = $versionManager; $this->disableListing = !$config->getSystemValue('debug', false); } @@ -54,12 +69,12 @@ class RootCollection extends AbstractPrincipalCollection { * @return INode */ public function getChildForPrincipal(array $principalInfo) { - list(,$name) = \Sabre\Uri\split($principalInfo['uri']); + 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 VersionHome($principalInfo, $this->rootFolder); + return new VersionHome($principalInfo, $this->rootFolder, $this->userManager, $this->versionManager); } public function getName() { diff --git a/apps/files_versions/lib/Sabre/VersionCollection.php b/apps/files_versions/lib/Sabre/VersionCollection.php index 481a5f491c3..9a3a6a365f0 100644 --- a/apps/files_versions/lib/Sabre/VersionCollection.php +++ b/apps/files_versions/lib/Sabre/VersionCollection.php @@ -21,11 +21,15 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\Files_Versions\Sabre; use OCA\Files_Versions\Storage; +use OCA\Files_Versions\Versions\IVersion; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\Files\File; use OCP\Files\Folder; +use OCP\IUser; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\ICollection; @@ -37,13 +41,17 @@ class VersionCollection implements ICollection { /** @var File */ private $file; - /** @var string */ - private $userId; + /** @var IUser */ + private $user; + + /** @var IVersionManager */ + private $versionManager; - public function __construct(Folder $userFolder, File $file, string $userId) { + public function __construct(Folder $userFolder, File $file, IUser $user, IVersionManager $versionManager) { $this->userFolder = $userFolder; $this->file = $file; - $this->userId = $userId; + $this->user = $user; + $this->versionManager = $versionManager; } public function createFile($name, $data = null) { @@ -68,10 +76,10 @@ class VersionCollection implements ICollection { } public function getChildren(): array { - $versions = Storage::getVersions($this->userId, $this->userFolder->getRelativePath($this->file->getPath())); + $versions = $this->versionManager->getVersionsForFile($this->user, $this->file); - return array_map(function (array $data) { - return new VersionFile($data, $this->userFolder->getParent()); + return array_map(function (IVersion $version) { + return new VersionFile($version, $this->versionManager); }, $versions); } diff --git a/apps/files_versions/lib/Sabre/VersionFile.php b/apps/files_versions/lib/Sabre/VersionFile.php index 347058448fc..2d630008d2a 100644 --- a/apps/files_versions/lib/Sabre/VersionFile.php +++ b/apps/files_versions/lib/Sabre/VersionFile.php @@ -21,26 +21,26 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\Files_Versions\Sabre; -use OCA\Files_Versions\Storage; -use OCP\Files\File; -use OCP\Files\Folder; +use OCA\Files_Versions\Versions\IVersion; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\Files\NotFoundException; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\IFile; class VersionFile implements IFile { - /** @var array */ - private $data; + /** @var IVersion */ + private $version; - /** @var Folder */ - private $userRoot; + /** @var IVersionManager */ + private $versionManager; - public function __construct(array $data, Folder $userRoot) { - $this->data = $data; - $this->userRoot = $userRoot; + public function __construct(IVersion $version, IVersionManager $versionManager) { + $this->version = $version; + $this->versionManager = $versionManager; } public function put($data) { @@ -49,27 +49,22 @@ class VersionFile implements IFile { public function get() { try { - /** @var Folder $versions */ - $versions = $this->userRoot->get('files_versions'); - /** @var File $version */ - $version = $versions->get($this->data['path'].'.v'.$this->data['version']); + return $this->versionManager->read($this->version); } catch (NotFoundException $e) { throw new NotFound(); } - - return $version->fopen('rb'); } public function getContentType(): string { - return $this->data['mimetype']; + return $this->version->getMimeType(); } public function getETag(): string { - return $this->data['version']; + return (string)$this->version->getRevisionId(); } public function getSize(): int { - return $this->data['size']; + return $this->version->getSize(); } public function delete() { @@ -77,7 +72,7 @@ class VersionFile implements IFile { } public function getName(): string { - return $this->data['version']; + return (string)$this->version->getRevisionId(); } public function setName($name) { @@ -85,10 +80,10 @@ class VersionFile implements IFile { } public function getLastModified(): int { - return (int)$this->data['version']; + return $this->version->getTimestamp(); } - public function rollBack(): bool { - return Storage::rollback($this->data['path'], $this->data['version']); + public function rollBack() { + $this->versionManager->rollback($this->version); } } diff --git a/apps/files_versions/lib/Sabre/VersionHome.php b/apps/files_versions/lib/Sabre/VersionHome.php index 7a99d2376d4..7be5974bbbe 100644 --- a/apps/files_versions/lib/Sabre/VersionHome.php +++ b/apps/files_versions/lib/Sabre/VersionHome.php @@ -20,9 +20,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\Files_Versions\Sabre; +use OC\User\NoUserException; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\Files\IRootFolder; +use OCP\IUserManager; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\ICollection; @@ -34,9 +38,25 @@ class VersionHome implements ICollection { /** @var IRootFolder */ private $rootFolder; - public function __construct(array $principalInfo, IRootFolder $rootFolder) { + /** @var IUserManager */ + private $userManager; + + /** @var IVersionManager */ + private $versionManager; + + public function __construct(array $principalInfo, IRootFolder $rootFolder, IUserManager $userManager, IVersionManager $versionManager) { $this->principalInfo = $principalInfo; $this->rootFolder = $rootFolder; + $this->userManager = $userManager; + $this->versionManager = $versionManager; + } + + private function getUser() { + list(, $name) = \Sabre\Uri\split($this->principalInfo['uri']); + $user = $this->userManager->get($name); + if (!$user) { + throw new NoUserException(); + } } public function delete() { @@ -44,8 +64,7 @@ class VersionHome implements ICollection { } public function getName(): string { - list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']); - return $name; + return $this->getUser()->getUID(); } public function setName($name) { @@ -61,22 +80,22 @@ class VersionHome implements ICollection { } public function getChild($name) { - list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + $user = $this->getUser(); if ($name === 'versions') { - return new VersionRoot($userId, $this->rootFolder); + return new VersionRoot($user, $this->rootFolder, $this->versionManager); } if ($name === 'restore') { - return new RestoreFolder($userId); + return new RestoreFolder(); } } public function getChildren() { - list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + $user = $this->getUser(); return [ - new VersionRoot($userId, $this->rootFolder), - new RestoreFolder($userId), + new VersionRoot($user, $this->rootFolder, $this->versionManager), + new RestoreFolder(), ]; } diff --git a/apps/files_versions/lib/Sabre/VersionRoot.php b/apps/files_versions/lib/Sabre/VersionRoot.php index 743b1c6ef1b..1c689a4d87b 100644 --- a/apps/files_versions/lib/Sabre/VersionRoot.php +++ b/apps/files_versions/lib/Sabre/VersionRoot.php @@ -23,23 +23,29 @@ declare(strict_types=1); */ namespace OCA\Files_Versions\Sabre; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\Files\File; use OCP\Files\IRootFolder; +use OCP\IUser; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\ICollection; class VersionRoot implements ICollection { - /** @var string */ - private $userId; + /** @var IUser */ + private $user; /** @var IRootFolder */ private $rootFolder; - public function __construct(string $userId, IRootFolder $rootFolder) { - $this->userId = $userId; + /** @var IVersionManager */ + private $versionManager; + + public function __construct(IUser $user, IRootFolder $rootFolder, IVersionManager $versionManager) { + $this->user = $user; $this->rootFolder = $rootFolder; + $this->versionManager = $versionManager; } public function delete() { @@ -63,7 +69,7 @@ class VersionRoot implements ICollection { } public function getChild($name) { - $userFolder = $this->rootFolder->getUserFolder($this->userId); + $userFolder = $this->rootFolder->getUserFolder($this->user->getUID()); $fileId = (int)$name; $nodes = $userFolder->getById($fileId); @@ -78,7 +84,7 @@ class VersionRoot implements ICollection { throw new NotFound(); } - return new VersionCollection($userFolder, $node, $this->userId); + return new VersionCollection($userFolder, $node, $this->user, $this->versionManager); } public function getChildren(): array { diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index 401544cc5d7..e2e4888cbce 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -48,6 +48,7 @@ use OC\Files\View; use OCA\Files_Versions\AppInfo\Application; use OCA\Files_Versions\Command\Expire; use OCA\Files_Versions\Events\CreateVersionEvent; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\Files\NotFoundException; use OCP\Lock\ILockingProvider; use OCP\User; @@ -178,10 +179,10 @@ class Storage { list($uid, $filename) = self::getUidAndFilename($filename); $files_view = new View('/'.$uid .'/files'); - $users_view = new View('/'.$uid); $eventDispatcher = \OC::$server->getEventDispatcher(); - $id = $files_view->getFileInfo($filename)->getId(); + $fileInfo = $files_view->getFileInfo($filename); + $id = $fileInfo->getId(); $nodes = \OC::$server->getRootFolder()->getById($id); foreach ($nodes as $node) { $event = new CreateVersionEvent($node); @@ -192,20 +193,16 @@ class Storage { } // no use making versions for empty files - if ($files_view->filesize($filename) === 0) { + if ($fileInfo->getSize() === 0) { return false; } - // create all parent folders - self::createMissingDirectories($filename, $users_view); - - self::scheduleExpire($uid, $filename); + /** @var IVersionManager $versionManager */ + $versionManager = \OC::$server->query(IVersionManager::class); + $userManager = \OC::$server->getUserManager(); + $user = $userManager->get($uid); - // store a new version of a file - $mtime = $users_view->filemtime('files/' . $filename); - $users_view->copy('files/' . $filename, 'files_versions/' . $filename . '.v' . $mtime); - // call getFileInfo to enforce a file cache entry for the new version - $users_view->getFileInfo('files_versions/' . $filename . '.v' . $mtime); + $versionManager->createVersion($user, $fileInfo); } @@ -695,7 +692,7 @@ class Storage { * @param string $uid owner of the file * @param string $fileName file/folder for which to schedule expiration */ - private static function scheduleExpire($uid, $fileName) { + public static function scheduleExpire($uid, $fileName) { // let the admin disable auto expire $expiration = self::getExpiration(); if ($expiration->isEnabled()) { @@ -833,7 +830,7 @@ class Storage { * "files" folder * @param View $view view on data/user/ */ - private static function createMissingDirectories($filename, $view) { + public static function createMissingDirectories($filename, $view) { $dirname = Filesystem::normalizePath(dirname($filename)); $dirParts = explode('/', $dirname); $dir = "/files_versions"; diff --git a/apps/files_versions/lib/Versions/BackendNotFoundException.php b/apps/files_versions/lib/Versions/BackendNotFoundException.php new file mode 100644 index 00000000000..09985a716b9 --- /dev/null +++ b/apps/files_versions/lib/Versions/BackendNotFoundException.php @@ -0,0 +1,26 @@ +<?php +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +class BackendNotFoundException extends \Exception { + +} diff --git a/apps/files_versions/lib/Versions/IVersion.php b/apps/files_versions/lib/Versions/IVersion.php new file mode 100644 index 00000000000..b6fc95814d8 --- /dev/null +++ b/apps/files_versions/lib/Versions/IVersion.php @@ -0,0 +1,99 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +use OCP\Files\FileInfo; +use OCP\IUser; + +/** + * @since 15.0.0 + */ +interface IVersion { + /** + * @return IVersionBackend + * @since 15.0.0 + */ + public function getBackend(): IVersionBackend; + + /** + * Get the file info of the source file + * + * @return FileInfo + * @since 15.0.0 + */ + public function getSourceFile(): FileInfo; + + /** + * Get the id of the revision for the file + * + * @return int + * @since 15.0.0 + */ + public function getRevisionId(): int; + + /** + * Get the timestamp this version was created + * + * @return int + * @since 15.0.0 + */ + public function getTimestamp(): int; + + /** + * Get the size of this version + * + * @return int + * @since 15.0.0 + */ + public function getSize(): int; + + /** + * Get the name of the source file at the time of making this version + * + * @return string + * @since 15.0.0 + */ + public function getSourceFileName(): string; + + /** + * Get the mimetype of this version + * + * @return string + * @since 15.0.0 + */ + public function getMimeType(): string; + + /** + * Get the path of this version + * + * @return string + * @since 15.0.0 + */ + public function getVersionPath(): string; + + /** + * @return IUser + * @since 15.0.0 + */ + public function getUser(): IUser; +} diff --git a/apps/files_versions/lib/Versions/IVersionBackend.php b/apps/files_versions/lib/Versions/IVersionBackend.php new file mode 100644 index 00000000000..616d535f7fd --- /dev/null +++ b/apps/files_versions/lib/Versions/IVersionBackend.php @@ -0,0 +1,81 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +use OCP\Files\File; +use OCP\Files\FileInfo; +use OCP\Files\NotFoundException; +use OCP\Files\SimpleFS\ISimpleFile; +use OCP\IUser; + +/** + * @since 15.0.0 + */ +interface IVersionBackend { + /** + * Get all versions for a file + * + * @param IUser $user + * @param FileInfo $file + * @return IVersion[] + * @since 15.0.0 + */ + public function getVersionsForFile(IUser $user, FileInfo $file): array; + + /** + * Create a new version for a file + * + * @param IUser $user + * @param FileInfo $file + * @since 15.0.0 + */ + public function createVersion(IUser $user, FileInfo $file); + + /** + * Restore this version + * + * @param IVersion $version + * @since 15.0.0 + */ + public function rollback(IVersion $version); + + /** + * Open the file for reading + * + * @param IVersion $version + * @return resource + * @throws NotFoundException + * @since 15.0.0 + */ + public function read(IVersion $version); + + /** + * Get the preview for a specific version of a file + * + * @param IUser $user + * @param FileInfo $sourceFile + * @param int $revision + * @return ISimpleFile + * @since 15.0.0 + */ + public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File; +} diff --git a/apps/files_versions/lib/Versions/IVersionManager.php b/apps/files_versions/lib/Versions/IVersionManager.php new file mode 100644 index 00000000000..748b649b1a2 --- /dev/null +++ b/apps/files_versions/lib/Versions/IVersionManager.php @@ -0,0 +1,36 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +/** + * @since 15.0.0 + */ +interface IVersionManager extends IVersionBackend { + /** + * Register a new backend + * + * @param string $storageType + * @param IVersionBackend $backend + * @since 15.0.0 + */ + public function registerBackend(string $storageType, IVersionBackend $backend); +} diff --git a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php new file mode 100644 index 00000000000..7293aca641e --- /dev/null +++ b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php @@ -0,0 +1,105 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +use OC\Files\View; +use OCA\Files_Versions\Storage; +use OCP\Files\File; +use OCP\Files\FileInfo; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\IUser; + +class LegacyVersionsBackend implements IVersionBackend { + /** @var IRootFolder */ + private $rootFolder; + + public function __construct(IRootFolder $rootFolder) { + $this->rootFolder = $rootFolder; + } + + public function getVersionsForFile(IUser $user, FileInfo $file): array { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $versions = Storage::getVersions($user->getUID(), $userFolder->getRelativePath($file->getPath())); + + return array_map(function (array $data) use ($file, $user) { + return new Version( + (int)$data['version'], + (int)$data['version'], + $data['name'], + (int)$data['size'], + $data['mimetype'], + $data['path'], + $file, + $this, + $user + ); + }, $versions); + } + + public function createVersion(IUser $user, FileInfo $file) { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $relativePath = $userFolder->getRelativePath($file->getPath()); + $userView = new View('/' . $user->getUID()); + // create all parent folders + Storage::createMissingDirectories($relativePath, $userView); + + Storage::scheduleExpire($user->getUID(), $relativePath); + + // store a new version of a file + $userView->copy('files/' . $relativePath, 'files_versions/' . $relativePath . '.v' . $file->getMtime()); + // ensure the file is scanned + $userView->getFileInfo('files_versions/' . $relativePath . '.v' . $file->getMtime()); + } + + public function rollback(IVersion $version) { + return Storage::rollback($version->getVersionPath(), $version->getRevisionId()); + } + + private function getVersionFolder(IUser $user): Folder { + $userRoot = $this->rootFolder->getUserFolder($user->getUID()) + ->getParent(); + try { + /** @var Folder $folder */ + $folder = $userRoot->get('files_versions'); + return $folder; + } catch (NotFoundException $e) { + return $userRoot->newFolder('files_versions'); + } + } + + public function read(IVersion $version) { + $versions = $this->getVersionFolder($version->getUser()); + /** @var File $file */ + $file = $versions->get($version->getVersionPath() . '.v' . $version->getRevisionId()); + return $file->fopen('r'); + } + + public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $versionFolder = $this->getVersionFolder($user); + /** @var File $file */ + $file = $versionFolder->get($userFolder->getRelativePath($sourceFile->getPath()) . '.v' . $revision); + return $file; + } +} diff --git a/apps/files_versions/lib/Versions/Version.php b/apps/files_versions/lib/Versions/Version.php new file mode 100644 index 00000000000..5988234db61 --- /dev/null +++ b/apps/files_versions/lib/Versions/Version.php @@ -0,0 +1,113 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +use OCP\Files\FileInfo; +use OCP\IUser; + +class Version implements IVersion { + /** @var int */ + private $timestamp; + + /** @var int */ + private $revisionId; + + /** @var string */ + private $name; + + /** @var int */ + private $size; + + /** @var string */ + private $mimetype; + + /** @var string */ + private $path; + + /** @var FileInfo */ + private $sourceFileInfo; + + /** @var IVersionBackend */ + private $backend; + + /** @var IUser */ + private $user; + + public function __construct( + int $timestamp, + int $revisionId, + string $name, + int $size, + string $mimetype, + string $path, + FileInfo $sourceFileInfo, + IVersionBackend $backend, + IUser $user + ) { + $this->timestamp = $timestamp; + $this->revisionId = $revisionId; + $this->name = $name; + $this->size = $size; + $this->mimetype = $mimetype; + $this->path = $path; + $this->sourceFileInfo = $sourceFileInfo; + $this->backend = $backend; + $this->user = $user; + } + + public function getBackend(): IVersionBackend { + return $this->backend; + } + + public function getSourceFile(): FileInfo { + return $this->sourceFileInfo; + } + + public function getRevisionId(): int { + return $this->revisionId; + } + + public function getTimestamp(): int { + return $this->timestamp; + } + + public function getSize(): int { + return $this->size; + } + + public function getSourceFileName(): string { + return $this->name; + } + + public function getMimeType(): string { + return $this->mimetype; + } + + public function getVersionPath(): string { + return $this->path; + } + + public function getUser(): IUser { + return $this->user; + } +} diff --git a/apps/files_versions/lib/Versions/VersionManager.php b/apps/files_versions/lib/Versions/VersionManager.php new file mode 100644 index 00000000000..757b6002710 --- /dev/null +++ b/apps/files_versions/lib/Versions/VersionManager.php @@ -0,0 +1,93 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Versions\Versions; + +use OCP\Files\File; +use OCP\Files\FileInfo; +use OCP\Files\Storage\IStorage; +use OCP\IUser; + +class VersionManager implements IVersionManager { + /** @var IVersionBackend[] */ + private $backends = []; + + public function registerBackend(string $storageType, IVersionBackend $backend) { + $this->backends[$storageType] = $backend; + } + + /** + * @return IVersionBackend[] + */ + private function getBackends(): array { + return $this->backends; + } + + /** + * @param IStorage $storage + * @return IVersionBackend + * @throws BackendNotFoundException + */ + public function getBackendForStorage(IStorage $storage): IVersionBackend { + $fullType = get_class($storage); + $backends = $this->getBackends(); + $foundType = array_reduce(array_keys($backends), function ($type, $registeredType) use ($storage) { + if ( + $storage->instanceOfStorage($registeredType) && + ($type === '' || is_subclass_of($registeredType, $type)) + ) { + return $registeredType; + } else { + return $type; + } + }, ''); + if ($foundType === '') { + throw new BackendNotFoundException("Version backend for $fullType not found"); + } else { + return $backends[$foundType]; + } + } + + public function getVersionsForFile(IUser $user, FileInfo $file): array { + $backend = $this->getBackendForStorage($file->getStorage()); + return $backend->getVersionsForFile($user, $file); + } + + public function createVersion(IUser $user, FileInfo $file) { + $backend = $this->getBackendForStorage($file->getStorage()); + $backend->createVersion($user, $file); + } + + public function rollback(IVersion $version) { + $backend = $version->getBackend(); + return $backend->rollback($version); + } + + public function read(IVersion $version) { + $backend = $version->getBackend(); + return $backend->read($version); + } + + public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File { + $backend = $this->getBackendForStorage($sourceFile->getStorage()); + return $backend->getVersionFile($user, $sourceFile, $revision); + } +} diff --git a/apps/files_versions/tests/Controller/PreviewControllerTest.php b/apps/files_versions/tests/Controller/PreviewControllerTest.php index 384f43cf495..7c248b36349 100644 --- a/apps/files_versions/tests/Controller/PreviewControllerTest.php +++ b/apps/files_versions/tests/Controller/PreviewControllerTest.php @@ -20,9 +20,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\Files_Versions\Tests\Controller; +use OC\User\User; use OCA\Files_Versions\Controller\PreviewController; +use OCA\Files_Versions\Versions\IVersionManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\FileDisplayResponse; @@ -34,6 +37,8 @@ use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; use OCP\IPreview; use OCP\IRequest; +use OCP\IUser; +use OCP\IUserSession; use Test\TestCase; class PreviewControllerTest extends TestCase { @@ -50,23 +55,39 @@ class PreviewControllerTest extends TestCase { /** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */ private $previewManager; - /** @var PreviewController */ + /** @var PreviewController|\PHPUnit_Framework_MockObject_MockObject */ private $controller; + /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */ + private $userSession; + + /** @var IVersionManager|\PHPUnit_Framework_MockObject_MockObject */ + private $versionManager; + public function setUp() { parent::setUp(); $this->rootFolder = $this->createMock(IRootFolder::class); $this->userId = 'user'; + $user = $this->createMock(IUser::class); + $user->expects($this->any()) + ->method('getUID') + ->willReturn($this->userId); $this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class); $this->previewManager = $this->createMock(IPreview::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->userSession->expects($this->any()) + ->method('getUser') + ->willReturn($user); + $this->versionManager = $this->createMock(IVersionManager::class); $this->controller = new PreviewController( 'files_versions', $this->createMock(IRequest::class), $this->rootFolder, - $this->userId, + $this->userSession, $this->mimeTypeDetector, + $this->versionManager, $this->previewManager ); } @@ -102,24 +123,23 @@ class PreviewControllerTest extends TestCase { public function testValidPreview() { $userFolder = $this->createMock(Folder::class); $userRoot = $this->createMock(Folder::class); - $versions = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->userId) ->willReturn($userFolder); $userFolder->method('getParent') ->willReturn($userRoot); - $userRoot->method('get') - ->with('files_versions') - ->willReturn($versions); - $this->mimeTypeDetector->method('detectPath') - ->with($this->equalTo('file')) - ->willReturn('myMime'); + $sourceFile = $this->createMock(File::class); + $userFolder->method('get') + ->with('file') + ->willReturn($sourceFile); $file = $this->createMock(File::class); - $versions->method('get') - ->with($this->equalTo('file.v42')) + $file->method('getMimetype') + ->willReturn('myMime'); + + $this->versionManager->method('getVersionFile') ->willReturn($file); $preview = $this->createMock(ISimpleFile::class); @@ -138,24 +158,23 @@ class PreviewControllerTest extends TestCase { public function testVersionNotFound() { $userFolder = $this->createMock(Folder::class); $userRoot = $this->createMock(Folder::class); - $versions = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->userId) ->willReturn($userFolder); $userFolder->method('getParent') ->willReturn($userRoot); - $userRoot->method('get') - ->with('files_versions') - ->willReturn($versions); + + $sourceFile = $this->createMock(File::class); + $userFolder->method('get') + ->with('file') + ->willReturn($sourceFile); $this->mimeTypeDetector->method('detectPath') ->with($this->equalTo('file')) ->willReturn('myMime'); - $file = $this->createMock(File::class); - $versions->method('get') - ->with($this->equalTo('file.v42')) + $this->versionManager->method('getVersionFile') ->willThrowException(new NotFoundException()); $res = $this->controller->getPreview('file', 10, 10, '42'); diff --git a/apps/oauth2/lib/Controller/OauthApiController.php b/apps/oauth2/lib/Controller/OauthApiController.php index 2083741fa0c..73fed3654d5 100644 --- a/apps/oauth2/lib/Controller/OauthApiController.php +++ b/apps/oauth2/lib/Controller/OauthApiController.php @@ -22,8 +22,9 @@ namespace OCA\OAuth2\Controller; use OC\Authentication\Exceptions\InvalidTokenException; -use OC\Authentication\Token\ExpiredTokenException; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Token\IProvider as TokenProvider; +use OC\Security\Bruteforce\Throttler; use OCA\OAuth2\Db\AccessTokenMapper; use OCA\OAuth2\Db\ClientMapper; use OCA\OAuth2\Exceptions\AccessTokenNotFoundException; @@ -49,6 +50,8 @@ class OauthApiController extends Controller { private $secureRandom; /** @var ITimeFactory */ private $time; + /** @var Throttler */ + private $throttler; /** * @param string $appName @@ -59,6 +62,7 @@ class OauthApiController extends Controller { * @param TokenProvider $tokenProvider * @param ISecureRandom $secureRandom * @param ITimeFactory $time + * @param Throttler $throttler */ public function __construct($appName, IRequest $request, @@ -67,7 +71,8 @@ class OauthApiController extends Controller { ClientMapper $clientMapper, TokenProvider $tokenProvider, ISecureRandom $secureRandom, - ITimeFactory $time) { + ITimeFactory $time, + Throttler $throttler) { parent::__construct($appName, $request); $this->crypto = $crypto; $this->accessTokenMapper = $accessTokenMapper; @@ -75,6 +80,7 @@ class OauthApiController extends Controller { $this->tokenProvider = $tokenProvider; $this->secureRandom = $secureRandom; $this->time = $time; + $this->throttler = $throttler; } /** @@ -164,6 +170,8 @@ class OauthApiController extends Controller { $accessToken->setEncryptedToken($this->crypto->encrypt($newToken, $newCode)); $this->accessTokenMapper->update($accessToken); + $this->throttler->resetDelay($this->request->getRemoteAddress(), 'login', ['user' => $appToken->getUID()]); + return new JSONResponse( [ 'access_token' => $newToken, diff --git a/apps/oauth2/tests/Controller/OauthApiControllerTest.php b/apps/oauth2/tests/Controller/OauthApiControllerTest.php index 10748485971..f5a8138fa2d 100644 --- a/apps/oauth2/tests/Controller/OauthApiControllerTest.php +++ b/apps/oauth2/tests/Controller/OauthApiControllerTest.php @@ -22,11 +22,10 @@ namespace OCA\OAuth2\Tests\Controller; use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Token\DefaultToken; -use OC\Authentication\Token\DefaultTokenMapper; -use OC\Authentication\Token\ExpiredTokenException; use OC\Authentication\Token\IProvider as TokenProvider; -use OC\Authentication\Token\IToken; +use OC\Security\Bruteforce\Throttler; use OCA\OAuth2\Controller\OauthApiController; use OCA\OAuth2\Db\AccessToken; use OCA\OAuth2\Db\AccessTokenMapper; @@ -57,6 +56,8 @@ class OauthApiControllerTest extends TestCase { private $secureRandom; /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */ private $time; + /** @var Throttler|\PHPUnit_Framework_MockObject_MockObject */ + private $throttler; /** @var OauthApiController */ private $oauthApiController; @@ -70,6 +71,7 @@ class OauthApiControllerTest extends TestCase { $this->tokenProvider = $this->createMock(TokenProvider::class); $this->secureRandom = $this->createMock(ISecureRandom::class); $this->time = $this->createMock(ITimeFactory::class); + $this->throttler = $this->createMock(Throttler::class); $this->oauthApiController = new OauthApiController( 'oauth2', @@ -79,7 +81,8 @@ class OauthApiControllerTest extends TestCase { $this->clientMapper, $this->tokenProvider, $this->secureRandom, - $this->time + $this->time, + $this->throttler ); } @@ -286,6 +289,17 @@ class OauthApiControllerTest extends TestCase { 'user_id' => 'userId', ]); + $this->request->method('getRemoteAddress') + ->willReturn('1.2.3.4'); + + $this->throttler->expects($this->once()) + ->method('resetDelay') + ->with( + '1.2.3.4', + 'login', + ['user' => 'userId'] + ); + $this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret')); } @@ -370,6 +384,17 @@ class OauthApiControllerTest extends TestCase { $this->request->server['PHP_AUTH_USER'] = 'clientId'; $this->request->server['PHP_AUTH_PW'] = 'clientSecret'; + $this->request->method('getRemoteAddress') + ->willReturn('1.2.3.4'); + + $this->throttler->expects($this->once()) + ->method('resetDelay') + ->with( + '1.2.3.4', + 'login', + ['user' => 'userId'] + ); + $this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', null, null)); } @@ -451,6 +476,17 @@ class OauthApiControllerTest extends TestCase { 'user_id' => 'userId', ]); + $this->request->method('getRemoteAddress') + ->willReturn('1.2.3.4'); + + $this->throttler->expects($this->once()) + ->method('resetDelay') + ->with( + '1.2.3.4', + 'login', + ['user' => 'userId'] + ); + $this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret')); } } diff --git a/apps/sharebymail/tests/CapabilitiesTest.php b/apps/sharebymail/tests/CapabilitiesTest.php new file mode 100644 index 00000000000..b1545994199 --- /dev/null +++ b/apps/sharebymail/tests/CapabilitiesTest.php @@ -0,0 +1,51 @@ +<?php +/** + * @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\ShareByMail\Tests; + +use OCA\ShareByMail\Capabilities; +use Test\TestCase; + +class CapabilitiesTest extends TestCase { + /** @var Capabilities */ + private $capabilities; + + public function setUp() { + parent::setUp(); + + $this->capabilities = new Capabilities(); + } + + public function testGetCapabilities() { + $capabilities = [ + 'files_sharing' => + [ + 'sharebymail' => + [ + 'enabled' => true, + 'upload_files_drop' => ['enabled' => true], + 'password' => ['enabled' => true], + 'expire_date' => ['enabled' => true] + ] + ] + ]; + + $this->assertSame($capabilities, $this->capabilities->getCapabilities()); + } +} diff --git a/apps/systemtags/tests/Activity/SettingTest.php b/apps/systemtags/tests/Activity/SettingTest.php new file mode 100644 index 00000000000..40fcea750a6 --- /dev/null +++ b/apps/systemtags/tests/Activity/SettingTest.php @@ -0,0 +1,72 @@ +<?php +/** + * @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\SystemTags\Tests\Activity; + +use OCA\SystemTags\Activity\Setting; +use OCP\IL10N; +use Test\TestCase; + +class SettingTest extends TestCase { + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ + private $l; + /** @var Setting */ + private $setting; + + public function setUp() { + parent::setUp(); + $this->l = $this->createMock(IL10N::class); + + $this->setting = new Setting($this->l); + } + + public function testGetIdentifier() { + $this->assertSame('systemtags', $this->setting->getIdentifier()); + } + + public function testGetName() { + $this->l + ->expects($this->once()) + ->method('t') + ->with('<strong>System tags</strong> for a file have been modified') + ->willReturn('<strong>System tags</strong> for a file have been modified'); + + $this->assertSame('<strong>System tags</strong> for a file have been modified', $this->setting->getName()); + } + + public function testGetPriority() { + $this->assertSame(50, $this->setting->getPriority()); + } + + public function testCanChangeStream() { + $this->assertSame(true, $this->setting->canChangeStream()); + } + + public function testIsDefaultEnabledStream() { + $this->assertSame(true, $this->setting->isDefaultEnabledStream()); + } + + public function testCanChangeMail() { + $this->assertSame(true, $this->setting->canChangeMail()); + } + + public function testIsDefaultEnabledMail() { + $this->assertSame(false, $this->setting->isDefaultEnabledMail()); + } +} diff --git a/apps/theming/l10n/fr.js b/apps/theming/l10n/fr.js index ae4791e202f..0527c421061 100644 --- a/apps/theming/l10n/fr.js +++ b/apps/theming/l10n/fr.js @@ -8,7 +8,7 @@ OC.L10N.register( "Name cannot be empty" : "Le nom ne peut pas être vide", "The given name is too long" : "Le nom donné est trop long", "The given web address is too long" : "L'adresse web donnée est trop longue", - "The given legal notice address is too long" : "L'adresse de la notice légale donnée est trop longue", + "The given legal notice address is too long" : "L'adresse fournie pour la notice légale est trop longue", "The given privacy policy address is too long" : "L'adresse de la politique de confidentialité est trop longue", "The given slogan is too long" : "Le slogan donné est trop long", "The given color is invalid" : "La couleur donnée est invalide", @@ -40,7 +40,7 @@ OC.L10N.register( "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", - "Legal notice link" : "Lien de la notice légale", + "Legal notice link" : "Lien vers la notice légale", "Privacy policy link" : "Lien de la politique de confidentialité", "Header logo" : "Logo d'en-tête", "Upload new header logo" : "Téléverser un nouveau logo d'en-tête", diff --git a/apps/theming/l10n/fr.json b/apps/theming/l10n/fr.json index d9f49f28f62..c47487f9e42 100644 --- a/apps/theming/l10n/fr.json +++ b/apps/theming/l10n/fr.json @@ -6,7 +6,7 @@ "Name cannot be empty" : "Le nom ne peut pas être vide", "The given name is too long" : "Le nom donné est trop long", "The given web address is too long" : "L'adresse web donnée est trop longue", - "The given legal notice address is too long" : "L'adresse de la notice légale donnée est trop longue", + "The given legal notice address is too long" : "L'adresse fournie pour la notice légale est trop longue", "The given privacy policy address is too long" : "L'adresse de la politique de confidentialité est trop longue", "The given slogan is too long" : "Le slogan donné est trop long", "The given color is invalid" : "La couleur donnée est invalide", @@ -38,7 +38,7 @@ "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", - "Legal notice link" : "Lien de la notice légale", + "Legal notice link" : "Lien vers la notice légale", "Privacy policy link" : "Lien de la politique de confidentialité", "Header logo" : "Logo d'en-tête", "Upload new header logo" : "Téléverser un nouveau logo d'en-tête", diff --git a/apps/twofactor_backupcodes/l10n/tr.js b/apps/twofactor_backupcodes/l10n/tr.js index 303db19654e..cdd6fa5058e 100644 --- a/apps/twofactor_backupcodes/l10n/tr.js +++ b/apps/twofactor_backupcodes/l10n/tr.js @@ -23,7 +23,7 @@ OC.L10N.register( "Nextcloud backup codes" : "Nextcloud yedek kodları", "You created two-factor backup codes for your account" : "İki aşamalı kimlik doğrulama için yedek kodlarınızı oluşturdunuz", "Second-factor backup codes" : "İki aşamalı kimlik doğrulama yedek kodları", - "You have enabled two-factor authentication but have not yet generated backup codes. Be sure to do this in case you lose access to your second factor." : "İki aşamalı kimlik doğrulamasını etkinleştirmişsiniz ancak yedek kodlarını üretmemişsiniz. İkinci aşamaya erişemediğiniz zaman kullanabilmek için yedek kodlarını üretmeyi unutmayın.", + "You have enabled two-factor authentication but have not yet generated backup codes. Be sure to do this in case you lose access to your second factor." : "İki aşamalı kimlik doğrulamasını etkinleştirmiş ancak yedek kodlarını üretmemişsiniz. İkinci aşamaya erişemediğiniz zaman kullanabilmek için yedek kodlarını üretmeyi unutmayın.", "Backup code" : "Yedek kod", "Use backup code" : "Yedek kodu kullan", "Two factor backup codes" : "İki aşamalı kimlik doğrulama yedek kodları", diff --git a/apps/twofactor_backupcodes/l10n/tr.json b/apps/twofactor_backupcodes/l10n/tr.json index 8d3137f79c4..77b1b650a2e 100644 --- a/apps/twofactor_backupcodes/l10n/tr.json +++ b/apps/twofactor_backupcodes/l10n/tr.json @@ -21,7 +21,7 @@ "Nextcloud backup codes" : "Nextcloud yedek kodları", "You created two-factor backup codes for your account" : "İki aşamalı kimlik doğrulama için yedek kodlarınızı oluşturdunuz", "Second-factor backup codes" : "İki aşamalı kimlik doğrulama yedek kodları", - "You have enabled two-factor authentication but have not yet generated backup codes. Be sure to do this in case you lose access to your second factor." : "İki aşamalı kimlik doğrulamasını etkinleştirmişsiniz ancak yedek kodlarını üretmemişsiniz. İkinci aşamaya erişemediğiniz zaman kullanabilmek için yedek kodlarını üretmeyi unutmayın.", + "You have enabled two-factor authentication but have not yet generated backup codes. Be sure to do this in case you lose access to your second factor." : "İki aşamalı kimlik doğrulamasını etkinleştirmiş ancak yedek kodlarını üretmemişsiniz. İkinci aşamaya erişemediğiniz zaman kullanabilmek için yedek kodlarını üretmeyi unutmayın.", "Backup code" : "Yedek kod", "Use backup code" : "Yedek kodu kullan", "Two factor backup codes" : "İki aşamalı kimlik doğrulama yedek kodları", diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php index 98a1bbfa1b7..e25b7ee3126 100644 --- a/apps/user_ldap/composer/composer/autoload_classmap.php +++ b/apps/user_ldap/composer/composer/autoload_classmap.php @@ -56,7 +56,6 @@ return array( 'OCA\\User_LDAP\\Settings\\Section' => $baseDir . '/../lib/Settings/Section.php', 'OCA\\User_LDAP\\UserPluginManager' => $baseDir . '/../lib/UserPluginManager.php', 'OCA\\User_LDAP\\User\\DeletedUsersIndex' => $baseDir . '/../lib/User/DeletedUsersIndex.php', - 'OCA\\User_LDAP\\User\\IUserTools' => $baseDir . '/../lib/User/IUserTools.php', 'OCA\\User_LDAP\\User\\Manager' => $baseDir . '/../lib/User/Manager.php', 'OCA\\User_LDAP\\User\\OfflineUser' => $baseDir . '/../lib/User/OfflineUser.php', 'OCA\\User_LDAP\\User\\User' => $baseDir . '/../lib/User/User.php', diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php index 83e49daf0f3..23819055be4 100644 --- a/apps/user_ldap/composer/composer/autoload_static.php +++ b/apps/user_ldap/composer/composer/autoload_static.php @@ -71,7 +71,6 @@ class ComposerStaticInitUser_LDAP 'OCA\\User_LDAP\\Settings\\Section' => __DIR__ . '/..' . '/../lib/Settings/Section.php', 'OCA\\User_LDAP\\UserPluginManager' => __DIR__ . '/..' . '/../lib/UserPluginManager.php', 'OCA\\User_LDAP\\User\\DeletedUsersIndex' => __DIR__ . '/..' . '/../lib/User/DeletedUsersIndex.php', - 'OCA\\User_LDAP\\User\\IUserTools' => __DIR__ . '/..' . '/../lib/User/IUserTools.php', 'OCA\\User_LDAP\\User\\Manager' => __DIR__ . '/..' . '/../lib/User/Manager.php', 'OCA\\User_LDAP\\User\\OfflineUser' => __DIR__ . '/..' . '/../lib/User/OfflineUser.php', 'OCA\\User_LDAP\\User\\User' => __DIR__ . '/..' . '/../lib/User/User.php', diff --git a/apps/user_ldap/lib/Access.php b/apps/user_ldap/lib/Access.php index e05bc539a77..fb2582e8266 100644 --- a/apps/user_ldap/lib/Access.php +++ b/apps/user_ldap/lib/Access.php @@ -46,7 +46,6 @@ namespace OCA\User_LDAP; use OC\HintException; use OC\Hooks\PublicEmitter; use OCA\User_LDAP\Exceptions\ConstraintViolationException; -use OCA\User_LDAP\User\IUserTools; use OCA\User_LDAP\User\Manager; use OCA\User_LDAP\User\OfflineUser; use OCA\User_LDAP\Mapping\AbstractMapping; @@ -59,7 +58,7 @@ use OCP\IUserManager; * Class Access * @package OCA\User_LDAP */ -class Access extends LDAPUtility implements IUserTools { +class Access extends LDAPUtility { const UUID_ATTRIBUTES = ['entryuuid', 'nsuniqueid', 'objectguid', 'guid', 'ipauniqueid']; /** @var \OCA\User_LDAP\Connection */ @@ -624,9 +623,9 @@ class Access extends LDAPUtility implements IUserTools { $this->connection->setConfiguration(['ldapCacheTTL' => $originalTTL]); $altName = $this->createAltInternalOwnCloudName($intName, $isUser); - if(is_string($altName) && $mapper->map($fdn, $altName, $uuid)) { - if($this->ncUserManager instanceof PublicEmitter && $isUser) { - $this->ncUserManager->emit('\OC\User', 'assignedUserId', [$intName]); + if (is_string($altName) && $mapper->map($fdn, $altName, $uuid)) { + if ($this->ncUserManager instanceof PublicEmitter && $isUser) { + $this->ncUserManager->emit('\OC\User', 'assignedUserId', [$altName]); } $newlyMapped = true; return $altName; diff --git a/apps/user_ldap/lib/User/IUserTools.php b/apps/user_ldap/lib/User/IUserTools.php deleted file mode 100644 index 4ba9cebb1a6..00000000000 --- a/apps/user_ldap/lib/User/IUserTools.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\User_LDAP\User; - -/** - * IUserTools - * - * defines methods that are required by User class for LDAP interaction - */ -interface IUserTools { - public function getConnection(); - - public function readAttribute($dn, $attr, $filter = 'objectClass=*'); - - public function stringResemblesDN($string); - - public function dn2username($dn, $ldapname = null); - - public function username2dn($name); -} diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php index 9f2f3649777..13555f9e31b 100644 --- a/apps/user_ldap/lib/User/Manager.php +++ b/apps/user_ldap/lib/User/Manager.php @@ -45,7 +45,7 @@ use OCP\Notification\IManager as INotificationManager; * cache */ class Manager { - /** @var IUserTools */ + /** @var Access */ protected $access; /** @var IConfig */ @@ -110,11 +110,11 @@ class Manager { } /** - * @brief binds manager to an instance of IUserTools (implemented by - * Access). It needs to be assigned first before the manager can be used. - * @param IUserTools + * Binds manager to an instance of Access. + * It needs to be assigned first before the manager can be used. + * @param Access */ - public function setLdapAccess(IUserTools $access) { + public function setLdapAccess(Access $access) { $this->access = $access; } diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php index 02764a72eca..706424d3189 100644 --- a/apps/user_ldap/lib/User/User.php +++ b/apps/user_ldap/lib/User/User.php @@ -30,6 +30,7 @@ namespace OCA\User_LDAP\User; +use OCA\User_LDAP\Access; use OCA\User_LDAP\Connection; use OCA\User_LDAP\FilesystemHelper; use OCA\User_LDAP\LogWrapper; @@ -48,7 +49,7 @@ use OCP\Notification\IManager as INotificationManager; */ class User { /** - * @var IUserTools + * @var Access */ protected $access; /** @@ -110,8 +111,7 @@ class User { * @brief constructor, make sure the subclasses call this one! * @param string $username the internal username * @param string $dn the LDAP DN - * @param IUserTools $access an instance that implements IUserTools for - * LDAP interaction + * @param Access $access * @param IConfig $config * @param FilesystemHelper $fs * @param Image $image any empty instance @@ -120,7 +120,7 @@ class User { * @param IUserManager $userManager * @param INotificationManager $notificationManager */ - public function __construct($username, $dn, IUserTools $access, + public function __construct($username, $dn, Access $access, IConfig $config, FilesystemHelper $fs, Image $image, LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager, INotificationManager $notificationManager) { @@ -414,14 +414,23 @@ class User { * * @param string $displayName * @param string $displayName2 - * @returns string the effective display name + * @return string the effective display name */ public function composeAndStoreDisplayName($displayName, $displayName2 = '') { $displayName2 = (string)$displayName2; if($displayName2 !== '') { $displayName .= ' (' . $displayName2 . ')'; } - $this->store('displayName', $displayName); + $oldName = $this->config->getUserValue($this->uid, 'user_ldap', 'displayName', null); + if ($oldName !== $displayName) { + $this->store('displayName', $displayName); + $user = $this->userManager->get($this->getUsername()); + if (!empty($oldName) && $user instanceof \OC\User\User) { + // if it was empty, it would be a new record, not a change emitting the trigger could + // potentially cause a UniqueConstraintViolationException, depending on some factors. + $user->triggerChange('displayName', $displayName); + } + } return $displayName; } diff --git a/apps/user_ldap/tests/User/ManagerTest.php b/apps/user_ldap/tests/User/ManagerTest.php index 104a70ff700..5c111abdc4e 100644 --- a/apps/user_ldap/tests/User/ManagerTest.php +++ b/apps/user_ldap/tests/User/ManagerTest.php @@ -28,11 +28,13 @@ namespace OCA\User_LDAP\Tests\User; +use OCA\User_LDAP\Access; +use OCA\User_LDAP\Connection; use OCA\User_LDAP\FilesystemHelper; use OCA\User_LDAP\ILDAPWrapper; use OCA\User_LDAP\LogWrapper; -use OCA\User_LDAP\User\IUserTools; use OCA\User_LDAP\User\Manager; +use OCA\User_LDAP\User\User; use OCP\IAvatarManager; use OCP\IConfig; use OCP\IDBConnection; @@ -48,200 +50,181 @@ use OCP\Notification\IManager as INotificationManager; * @package OCA\User_LDAP\Tests\User */ class ManagerTest extends \Test\TestCase { + /** @var Access|\PHPUnit_Framework_MockObject_MockObject */ + protected $access; - private function getTestInstances() { - $access = $this->createMock(IUserTools::class); - $config = $this->createMock(IConfig::class); - $filesys = $this->createMock(FilesystemHelper::class); - $log = $this->createMock(LogWrapper::class); - $avaMgr = $this->createMock(IAvatarManager::class); - $image = $this->createMock(Image::class); - $dbc = $this->createMock(IDBConnection::class); - $userMgr = $this->createMock(IUserManager::class); - $notiMgr = $this->createMock(INotificationManager::class); - - $connection = new \OCA\User_LDAP\Connection( - $lw = $this->createMock(ILDAPWrapper::class), - '', - null - ); + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ + protected $config; - $access->expects($this->any()) - ->method('getConnection') - ->will($this->returnValue($connection)); + /** @var FilesystemHelper|\PHPUnit_Framework_MockObject_MockObject */ + protected $fileSystemHelper; - return array($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr); - } + /** @var LogWrapper|\PHPUnit_Framework_MockObject_MockObject */ + protected $log; - public function testGetByDNExisting() { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); + /** @var IAvatarManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $avatarManager; - $inputDN = 'cn=foo,dc=foobar,dc=bar'; - $uid = '563418fc-423b-1033-8d1c-ad5f418ee02e'; + /** @var Image|\PHPUnit_Framework_MockObject_MockObject */ + protected $image; - $access->expects($this->once()) - ->method('stringResemblesDN') - ->with($this->equalTo($inputDN)) - ->will($this->returnValue(true)); + /** @var IDBConnection|\PHPUnit_Framework_MockObject_MockObject */ + protected $dbc; - $access->expects($this->once()) - ->method('dn2username') - ->with($this->equalTo($inputDN)) - ->will($this->returnValue($uid)); + /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $ncUserManager; - $access->expects($this->never()) - ->method('username2dn'); + /** @var INotificationManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $notificationManager; - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - $user = $manager->get($inputDN); + /** @var ILDAPWrapper|\PHPUnit_Framework_MockObject_MockObject */ + protected $ldapWrapper; - // Now we fetch the user again. If this leads to a failing test, - // runtime caching the manager is broken. - $user = $manager->get($inputDN); - - $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user); - } + /** @var Connection */ + protected $connection; - public function testGetByEDirectoryDN() { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); + /** @var Manager */ + protected $manager; - $inputDN = 'uid=foo,o=foobar,c=bar'; - $uid = '563418fc-423b-1033-8d1c-ad5f418ee02e'; + public function setUp() { + parent::setUp(); - $access->expects($this->once()) - ->method('stringResemblesDN') - ->with($this->equalTo($inputDN)) - ->will($this->returnValue(true)); - - $access->expects($this->once()) - ->method('dn2username') - ->with($this->equalTo($inputDN)) - ->will($this->returnValue($uid)); + $this->access = $this->createMock(Access::class); + $this->config = $this->createMock(IConfig::class); + $this->fileSystemHelper = $this->createMock(FilesystemHelper::class); + $this->log = $this->createMock(LogWrapper::class); + $this->avatarManager = $this->createMock(IAvatarManager::class); + $this->image = $this->createMock(Image::class); + $this->dbc = $this->createMock(IDBConnection::class); + $this->ncUserManager = $this->createMock(IUserManager::class); + $this->notificationManager = $this->createMock(INotificationManager::class); - $access->expects($this->never()) - ->method('username2dn'); + $this->ldapWrapper = $this->createMock(ILDAPWrapper::class); + $this->connection = new Connection($this->ldapWrapper, '', null); - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - $user = $manager->get($inputDN); + $this->access->expects($this->any()) + ->method('getConnection') + ->will($this->returnValue($this->connection)); + + /** @noinspection PhpUnhandledExceptionInspection */ + $this->manager = new Manager( + $this->config, + $this->fileSystemHelper, + $this->log, + $this->avatarManager, + $this->image, + $this->dbc, + $this->ncUserManager, + $this->notificationManager + ); - $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user); + $this->manager->setLdapAccess($this->access); } - public function testGetByExoticDN() { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); + public function dnProvider() { + return [ + ['cn=foo,dc=foobar,dc=bar'], + ['uid=foo,o=foobar,c=bar'], + ['ab=cde,f=ghei,mno=pq'], + ]; + } - $inputDN = 'ab=cde,f=ghei,mno=pq'; + /** + * @dataProvider dnProvider + */ + public function testGetByDNExisting(string $inputDN) { $uid = '563418fc-423b-1033-8d1c-ad5f418ee02e'; - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('stringResemblesDN') ->with($this->equalTo($inputDN)) ->will($this->returnValue(true)); - - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('dn2username') ->with($this->equalTo($inputDN)) ->will($this->returnValue($uid)); - - $access->expects($this->never()) + $this->access->expects($this->never()) ->method('username2dn'); - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - $user = $manager->get($inputDN); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->manager->get($inputDN); - $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user); + // Now we fetch the user again. If this leads to a failing test, + // runtime caching the manager is broken. + /** @noinspection PhpUnhandledExceptionInspection */ + $user = $this->manager->get($inputDN); + + $this->assertInstanceOf(User::class, $user); } public function testGetByDNNotExisting() { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); - $inputDN = 'cn=gone,dc=foobar,dc=bar'; - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('stringResemblesDN') ->with($this->equalTo($inputDN)) ->will($this->returnValue(true)); - - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('dn2username') ->with($this->equalTo($inputDN)) ->will($this->returnValue(false)); - - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('username2dn') ->with($this->equalTo($inputDN)) ->will($this->returnValue(false)); - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - $user = $manager->get($inputDN); + /** @noinspection PhpUnhandledExceptionInspection */ + $user = $this->manager->get($inputDN); $this->assertNull($user); } public function testGetByUidExisting() { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); - $dn = 'cn=foo,dc=foobar,dc=bar'; $uid = '563418fc-423b-1033-8d1c-ad5f418ee02e'; - $access->expects($this->never()) + $this->access->expects($this->never()) ->method('dn2username'); - - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('username2dn') ->with($this->equalTo($uid)) ->will($this->returnValue($dn)); - - $access->expects($this->once()) + $this->access->expects($this->once()) ->method('stringResemblesDN') ->with($this->equalTo($uid)) ->will($this->returnValue(false)); - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - $user = $manager->get($uid); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->manager->get($uid); // Now we fetch the user again. If this leads to a failing test, // runtime caching the manager is broken. - $user = $manager->get($uid); + /** @noinspection PhpUnhandledExceptionInspection */ + $user = $this->manager->get($uid); - $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user); + $this->assertInstanceOf(User::class, $user); } public function testGetByUidNotExisting() { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); - $uid = 'gone'; - $access->expects($this->never()) + $this->access->expects($this->never()) ->method('dn2username'); - - $access->expects($this->exactly(1)) + $this->access->expects($this->exactly(1)) ->method('username2dn') ->with($this->equalTo($uid)) ->will($this->returnValue(false)); - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - $user = $manager->get($uid); + /** @noinspection PhpUnhandledExceptionInspection */ + $user = $this->manager->get($uid); $this->assertNull($user); } public function attributeRequestProvider() { return [ - [ false ], - [ true ], + [false], + [true], ]; } @@ -249,23 +232,16 @@ class ManagerTest extends \Test\TestCase { * @dataProvider attributeRequestProvider */ public function testGetAttributes($minimal) { - list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) = - $this->getTestInstances(); - - $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr); - $manager->setLdapAccess($access); - - $connection = $access->getConnection(); - $connection->setConfiguration([ + $this->connection->setConfiguration([ 'ldapEmailAttribute' => 'mail', 'ldapUserAvatarRule' => 'default', 'ldapQuotaAttribute' => '', ]); - $attributes = $manager->getAttributes($minimal); + $attributes = $this->manager->getAttributes($minimal); $this->assertTrue(in_array('dn', $attributes)); - $this->assertTrue(in_array($access->getConnection()->ldapEmailAttribute, $attributes)); + $this->assertTrue(in_array($this->access->getConnection()->ldapEmailAttribute, $attributes)); $this->assertFalse(in_array('', $attributes)); $this->assertSame(!$minimal, in_array('jpegphoto', $attributes)); $this->assertSame(!$minimal, in_array('thumbnailphoto', $attributes)); diff --git a/apps/user_ldap/tests/User/UserTest.php b/apps/user_ldap/tests/User/UserTest.php index 837c72a3a31..6ff9defe47b 100644 --- a/apps/user_ldap/tests/User/UserTest.php +++ b/apps/user_ldap/tests/User/UserTest.php @@ -998,23 +998,58 @@ class UserTest extends \Test\TestCase { public function displayNameProvider() { return [ - ['Roland Deschain', '', 'Roland Deschain'], - ['Roland Deschain', null, 'Roland Deschain'], - ['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)'], + ['Roland Deschain', '', 'Roland Deschain', false], + ['Roland Deschain', '', 'Roland Deschain', true], + ['Roland Deschain', null, 'Roland Deschain', false], + ['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)', false], + ['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)', true], ]; } /** * @dataProvider displayNameProvider */ - public function testComposeAndStoreDisplayName($part1, $part2, $expected) { + public function testComposeAndStoreDisplayName($part1, $part2, $expected, $expectTriggerChange) { $this->config->expects($this->once()) ->method('setUserValue'); + $oldName = $expectTriggerChange ? 'xxGunslingerxx' : null; + $this->config->expects($this->once()) + ->method('getUserValue') + ->with($this->user->getUsername(), 'user_ldap', 'displayName', null) + ->willReturn($oldName); + + $ncUserObj = $this->createMock(\OC\User\User::class); + if ($expectTriggerChange) { + $ncUserObj->expects($this->once()) + ->method('triggerChange') + ->with('displayName', $expected); + } else { + $ncUserObj->expects($this->never()) + ->method('triggerChange'); + } + $this->userManager->expects($this->once()) + ->method('get') + ->willReturn($ncUserObj); $displayName = $this->user->composeAndStoreDisplayName($part1, $part2); $this->assertSame($expected, $displayName); } + public function testComposeAndStoreDisplayNameNoOverwrite() { + $displayName = 'Randall Flagg'; + $this->config->expects($this->never()) + ->method('setUserValue'); + $this->config->expects($this->once()) + ->method('getUserValue') + ->willReturn($displayName); + + $this->userManager->expects($this->never()) + ->method('get'); // Implicit: no triggerChange can be called + + $composedDisplayName = $this->user->composeAndStoreDisplayName($displayName); + $this->assertSame($composedDisplayName, $displayName); + } + public function testHandlePasswordExpiryWarningDefaultPolicy() { $this->connection->expects($this->any()) ->method('__get') diff --git a/apps/workflowengine/lib/Check/FileMimeType.php b/apps/workflowengine/lib/Check/FileMimeType.php index bd94ec9d5bc..5f572f5aa9d 100644 --- a/apps/workflowengine/lib/Check/FileMimeType.php +++ b/apps/workflowengine/lib/Check/FileMimeType.php @@ -76,6 +76,11 @@ class FileMimeType extends AbstractStringCheck { return $this->mimeType[$this->storage->getId()][$this->path]; } + if ($this->storage->is_dir($this->path)) { + $this->mimeType[$this->storage->getId()][$this->path] = 'httpd/unix-directory'; + return $this->mimeType[$this->storage->getId()][$this->path]; + } + if ($this->isWebDAVRequest()) { // Creating a folder if ($this->request->getMethod() === 'MKCOL') { diff --git a/build/compile-handlebars-templates.sh b/build/compile-handlebars-templates.sh index 65ad4da12cf..b73b7d8f460 100755 --- a/build/compile-handlebars-templates.sh +++ b/build/compile-handlebars-templates.sh @@ -32,7 +32,7 @@ handlebars -n OCA.WorkflowEngine.Templates apps/workflowengine/js/templates -f a handlebars -n OCA.Sharing.Templates apps/files_sharing/js/templates -f apps/files_sharing/js/templates.js # Files external -handlebars -n OCA.External.Templates apps/files_external/js/templates -f apps/files_external/js/templates.js +handlebars -n OCA.Files_External.Templates apps/files_external/js/templates -f apps/files_external/js/templates.js if [[ $(git diff --name-only) ]]; then echo "Please submit your compiled handlebars templates" diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index 77fe811fada..a5fd8140518 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -8,7 +8,7 @@ Feature: webdav-related Then the HTTP status code should be "401" And there are no duplicate headers And The following headers should be set - |WWW-Authenticate|Basic realm="Nextcloud"| + |WWW-Authenticate|Basic realm="Nextcloud", charset="UTF-8"| Scenario: Unauthenticated call new dav path Given using new dav path @@ -16,7 +16,7 @@ Feature: webdav-related Then the HTTP status code should be "401" And there are no duplicate headers And The following headers should be set - |WWW-Authenticate|Basic realm="Nextcloud"| + |WWW-Authenticate|Basic realm="Nextcloud", charset="UTF-8"| Scenario: Moving a file Given using old dav path diff --git a/build/package-lock.json b/build/package-lock.json index afac3aee8bb..5248f3228cd 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -60,28 +60,12 @@ "negotiator": "0.6.1" } }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "dev": true, - "optional": true - }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -100,42 +84,6 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, - "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", - "dev": true, - "optional": true, - "requires": { - "bitsyntax": "~0.0.4", - "bluebird": "^3.4.6", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "^5.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -252,13 +200,6 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.6.tgz", - "integrity": "sha512-nHiuV14upVGl7MWwFUYbzJ6YlfwWS084CU9EA8HajfYQjMSli5TQi3UTRygGF58LFWVkXxS1rbgRhROEqlQkXg==", - "dev": true, - "optional": true - }, "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", @@ -310,28 +251,6 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, - "axios": { - "version": "0.15.3", - "resolved": "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "dev": true, - "optional": true, - "requires": { - "follow-redirects": "1.0.0" - }, - "dependencies": { - "follow-redirects": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.2.0" - } - } - } - }, "babylon": { "version": "7.0.0-beta.19", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", @@ -441,67 +360,9 @@ "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", "dev": true }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "0.0.2" - } - }, - "bl": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "~2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "blob": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", "dev": true }, @@ -538,15 +399,6 @@ "type-is": "~1.6.16" } }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, "bower": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz", @@ -620,28 +472,6 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", - "dev": true - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "dev": true, - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - } - }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -751,9 +581,9 @@ } }, "circular-json": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", - "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "class-utils": { @@ -937,16 +767,6 @@ "which": "^1.2.9" } }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x" - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -971,13 +791,6 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true, - "optional": true - }, "date-format": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", @@ -1062,18 +875,6 @@ } } }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "optional": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1116,13 +917,6 @@ "void-elements": "^2.0.0" } }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1146,9 +940,9 @@ "dev": true }, "engine.io": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", - "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", + "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -1156,7 +950,6 @@ "cookie": "0.3.1", "debug": "~3.1.0", "engine.io-parser": "~2.1.0", - "uws": "~9.14.0", "ws": "~3.3.1" }, "dependencies": { @@ -1172,9 +965,9 @@ } }, "engine.io-client": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", - "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -1235,15 +1028,6 @@ "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1256,33 +1040,6 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", - "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", - "dev": true, - "optional": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true, - "optional": true - }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", @@ -1519,13 +1276,6 @@ "pend": "~1.2.0" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1714,12 +1464,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1734,17 +1486,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -1861,7 +1616,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -1873,6 +1629,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -1887,6 +1644,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1894,12 +1652,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -1918,6 +1678,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -1998,7 +1759,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2010,6 +1772,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2131,6 +1894,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2214,39 +1978,6 @@ "rimraf": "2" } }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -2272,26 +2003,6 @@ "globule": "^1.0.0" } }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "optional": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "optional": true, - "requires": { - "is-property": "^1.0.0" - } - }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -2304,21 +2015,6 @@ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", - "dev": true, - "optional": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - } - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -2500,36 +2196,6 @@ "pinkie-promise": "^2.0.0" } }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "dev": true, - "optional": true, - "requires": { - "lodash": "^4.0.0", - "request": "^2.0.0" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -2559,27 +2225,6 @@ "requires-port": "^1.0.0" } }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -2591,57 +2236,6 @@ "sshpk": "^1.7.0" } }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true, - "requires": { - "httpreq": ">=0.4.22", - "underscore": "~1.7.0" - }, - "dependencies": { - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true - } - } - }, - "httpreq": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true - }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -2672,13 +2266,6 @@ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true, - "optional": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2701,12 +2288,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -2835,27 +2416,6 @@ "is-extglob": "^2.1.1" } }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true, - "optional": true - }, - "is-my-json-valid": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", - "dev": true, - "optional": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -2885,12 +2445,6 @@ "isobject": "^3.0.1" } }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3148,13 +2702,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true, - "optional": true - }, "jsonschema": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", @@ -3180,9 +2727,9 @@ "dev": true }, "karma": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", - "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.1.tgz", + "integrity": "sha512-NetT3wPCQMNB36uiL9LLyhrOt8SQwrEKt0xD3+KpTCfm0VxVyUJdPL5oTq2Ic5ouemgL/Iz4wqXEbF3zea9kQQ==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -3200,15 +2747,15 @@ "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", "lodash": "^4.17.4", - "log4js": "^2.5.3", - "mime": "^1.3.4", + "log4js": "^3.0.0", + "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", "qjobs": "^1.1.4", "range-parser": "^1.2.0", "rimraf": "^2.6.0", "safe-buffer": "^5.0.1", - "socket.io": "2.0.4", + "socket.io": "2.1.1", "source-map": "^0.6.1", "tmp": "0.0.33", "useragent": "2.2.1" @@ -3317,37 +2864,6 @@ "type-check": "~0.3.2" } }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "dev": true, - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true - }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -3398,23 +2914,15 @@ "dev": true }, "log4js": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", - "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { - "amqplib": "^0.5.2", - "axios": "^0.15.3", - "circular-json": "^0.5.4", + "circular-json": "^0.5.5", "date-format": "^1.2.0", "debug": "^3.1.0", - "hipchat-notifier": "^1.1.0", - "loggly": "^1.1.0", - "mailgun-js": "^0.18.0", - "nodemailer": "^2.5.0", - "redis": "^2.7.1", - "semver": "^5.5.0", - "slack-node": "~0.2.0", + "rfdc": "^1.1.2", "streamroller": "0.7.0" }, "dependencies": { @@ -3435,146 +2943,6 @@ } } }, - "loggly": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", - "dev": true, - "optional": true, - "requires": { - "json-stringify-safe": "5.0.x", - "request": "2.75.x", - "timespan": "2.3.x" - }, - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.11" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "optional": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true, - "optional": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "optional": true - }, - "request": { - "version": "2.75.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.0.0", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "optional": true, - "requires": { - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true, - "optional": true - } - } - }, "lolex": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", @@ -3601,47 +2969,6 @@ "yallist": "^2.1.2" } }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "dev": true, - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } - }, - "mailgun-js": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", - "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", - "dev": true, - "optional": true, - "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -3671,7 +2998,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, @@ -3723,9 +3050,9 @@ } }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", "dev": true }, "mime-db": { @@ -3833,13 +3160,6 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true, - "optional": true - }, "nise": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", @@ -3919,98 +3239,6 @@ "true-case-path": "^1.0.2" } }, - "nodemailer": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "dev": true, - "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - }, - "dependencies": { - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true, - "optional": true - }, - "socks": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.2", - "smart-buffer": "^1.0.4" - } - } - } - }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "1.6.0" - } - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -4207,56 +3435,6 @@ "os-tmpdir": "^1.0.0" } }, - "pac-proxy-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", - "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "optional": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -4317,25 +3495,6 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "optional": true, - "requires": { - "inflection": "~1.3.0" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true, - "optional": true - } - } - }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", @@ -4430,59 +3589,6 @@ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "dev": true, - "optional": true, - "requires": { - "with-callback": "^1.0.2" - } - }, - "proxy-agent": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", - "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^3.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - } - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true, - "optional": true - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -4596,32 +3702,6 @@ "strip-indent": "^1.0.1" } }, - "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", - "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" - } - }, - "redis-commands": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", - "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==", - "dev": true, - "optional": true - }, - "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", - "dev": true, - "optional": true - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -4696,19 +3776,6 @@ "throttleit": "^1.0.0" } }, - "requestretry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", - "dev": true, - "optional": true, - "requires": { - "extend": "^3.0.0", - "lodash": "^4.15.0", - "request": "^2.74.0", - "when": "^3.7.7" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4762,6 +3829,12 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -4893,32 +3966,6 @@ "type-detect": "^4.0.5" } }, - "slack-node": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "dev": true, - "optional": true, - "requires": { - "requestretry": "^1.2.2" - } - }, - "smart-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", - "dev": true - }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5032,27 +4079,29 @@ } } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "optional": true, - "requires": { - "hoek": "2.x.x" - } - }, "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "debug": "~2.6.6", - "engine.io": "~3.1.0", + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.0.4", - "socket.io-parser": "~3.1.1" + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "socket.io-adapter": { @@ -5062,35 +4111,46 @@ "dev": true }, "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~2.6.4", - "engine.io-client": "~3.1.0", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.1.1", + "socket.io-parser": "~3.2.0", "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "socket.io-parser": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", - "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { "component-emitter": "1.2.1", "debug": "~3.1.0", - "has-binary2": "~1.0.2", "isarray": "2.0.1" }, "dependencies": { @@ -5111,26 +4171,6 @@ } } }, - "socks": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", - "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", - "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", - "dev": true, - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5305,13 +4345,6 @@ "safe-buffer": "~5.1.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true, - "optional": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -5383,20 +4416,6 @@ "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", "dev": true }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true, - "optional": true - }, - "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true, - "optional": true - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -5479,13 +4498,6 @@ "glob": "^7.1.2" } }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "dev": true, - "optional": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5713,13 +4725,6 @@ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true }, - "uws": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", - "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", - "dev": true, - "optional": true - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -5747,13 +4752,6 @@ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true, - "optional": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5778,13 +4776,6 @@ "string-width": "^1.0.2 || 2" } }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", - "dev": true, - "optional": true - }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -5836,20 +4827,6 @@ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true, - "optional": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true, - "optional": true - }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", diff --git a/build/package.json b/build/package.json index 420980c94cc..1325406b749 100644 --- a/build/package.json +++ b/build/package.json @@ -16,7 +16,7 @@ "jasmine-core": "~2.5.2", "jasmine-sinon": "^0.4.0", "jsdoc": "^3.5.5", - "karma": "^2.0.2", + "karma": "^3.1.1", "karma-coverage": "*", "karma-jasmine": "^1.1.2", "karma-jasmine-sinon": "^1.0.4", diff --git a/config/config.sample.php b/config/config.sample.php index 9a5648c95df..902bfa6e44d 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1499,11 +1499,26 @@ $CONFIG = array( /** * List of trusted proxy servers * - * If you configure these also consider setting `forwarded_for_headers` which - * otherwise defaults to `HTTP_X_FORWARDED_FOR` (the `X-Forwarded-For` header). + * You may set this to an array containing a combination of + * - IPv4 addresses, e.g. `192.168.2.123` + * - IPv4 ranges in CIDR notation, e.g. `192.168.2.0/24` + * - IPv6 addresses, e.g. `fd9e:21a7:a92c:2323::1` + * + * _(CIDR notation for IPv6 is currently work in progress and thus not + * available as of yet)_ + * + * When an incoming request's `REMOTE_ADDR` matches any of the IP addresses + * specified here, it is assumed to be a proxy instead of a client. Thus, the + * client IP will be read from the HTTP header specified in + * `forwarded_for_headers` instead of from `REMOTE_ADDR`. + * + * So if you configure `trusted_proxies`, also consider setting + * `forwarded_for_headers` which otherwise defaults to `HTTP_X_FORWARDED_FOR` + * (the `X-Forwarded-For` header). + * * Defaults to an empty array. */ -'trusted_proxies' => array('203.0.113.45', '198.51.100.128'), +'trusted_proxies' => array('203.0.113.45', '198.51.100.128', '192.168.2.0/24'), /** * Headers that should be trusted as client IP address in combination with @@ -1648,4 +1663,14 @@ $CONFIG = array( * If this is set to "false" it will not show the link. */ 'simpleSignUpLink.shown' => true, + +/** + * By default autocompletion is enabled for the login form on Nextcloud's login page. + * While this is enabled, browsers are allowed to "remember" login names and such. + * Some companies require it to be disabled to comply with their security policy. + * + * Simply set this property to "false", if you want to turn this feature off. + */ + +'login_form_autocomplete' => true, ); diff --git a/core/Command/App/Remove.php b/core/Command/App/Remove.php new file mode 100644 index 00000000000..71d5cef229c --- /dev/null +++ b/core/Command/App/Remove.php @@ -0,0 +1,149 @@ +<?php +/** + * @copyright Copyright (c) 2018, Patrik Kernstock <info@pkern.at> + * + * @author Patrik Kernstock <info@pkern.at> + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\Core\Command\App; + +use Throwable; +use OC\Installer; +use OCP\App\IAppManager; +use OCP\ILogger; +use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface; +use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Remove extends Command implements CompletionAwareInterface { + + /** @var IAppManager */ + protected $manager; + /** @var Installer */ + private $installer; + /** @var ILogger */ + private $logger; + + /** + * @param IAppManager $manager + * @param Installer $installer + * @param ILogger $logger + */ + public function __construct(IAppManager $manager, Installer $installer, ILogger $logger) { + parent::__construct(); + $this->manager = $manager; + $this->installer = $installer; + $this->logger = $logger; + } + + protected function configure() { + $this + ->setName('app:remove') + ->setDescription('remove an app') + ->addArgument( + 'app-id', + InputArgument::REQUIRED, + 'remove the specified app' + ) + ->addOption( + 'keep-data', + null, + InputOption::VALUE_NONE, + 'keep app data and do not remove them' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $appId = $input->getArgument('app-id'); + + // Check if the app is installed + if (!\OC_App::getAppPath($appId)) { + $output->writeln($appId . ' is not installed'); + return 1; + } + + // Removing shipped apps is not possible, therefore we pre-check that + // before trying to remove it + if ($this->manager->isShipped($appId)) { + $output->writeln($appId . ' could not be removed as it is a shipped app'); + return 1; + } + + // If we want to keep the data of the app, we simply don't disable it here. + // App uninstall tasks are being executed when disabled. More info: PR #11627. + if (!$input->getOption('keep-data')) { + try { + $this->manager->disableApp($appId); + $output->writeln($appId . ' disabled'); + } catch(Throwable $e) { + $output->writeln('<error>Error: ' . $e->getMessage() . '</error>'); + $this->logger->logException($e, [ + 'app' => 'CLI', + 'level' => ILogger::ERROR + ]); + return 1; + } + } + + // Let's try to remove the app... + try { + $result = $this->installer->removeApp($appId); + } catch(Throwable $e) { + $output->writeln('<error>Error: ' . $e->getMessage() . '</error>'); + $this->logger->logException($e, [ + 'app' => 'CLI', + 'level' => ILogger::ERROR + ]); + return 1; + } + + if($result === false) { + $output->writeln($appId . ' could not be removed'); + return 1; + } + + $output->writeln($appId . ' removed'); + + return 0; + } + + /** + * @param string $optionName + * @param CompletionContext $context + * @return string[] + */ + public function completeOptionValues($optionName, CompletionContext $context) { + return []; + } + + /** + * @param string $argumentName + * @param CompletionContext $context + * @return string[] + */ + public function completeArgumentValues($argumentName, CompletionContext $context) { + if ($argumentName === 'app-id') { + return \OC_App::getAllApps(); + } + return []; + } +} diff --git a/core/Command/App/Update.php b/core/Command/App/Update.php new file mode 100644 index 00000000000..c571a9a1624 --- /dev/null +++ b/core/Command/App/Update.php @@ -0,0 +1,125 @@ +<?php +/** + * @copyright Copyright (c) 2018, michag86 (michag86@arcor.de) + * + * @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 OC\Core\Command\App; + +use OCP\App\IAppManager; +use OC\Installer; +use OCP\ILogger; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Update extends Command { + + /** @var IAppManager */ + protected $manager; + /** @var Installer */ + private $installer; + /** @var ILogger */ + private $logger; + + /** + * @param IAppManager $manager + * @param Installer $installer + */ + public function __construct(IAppManager $manager, Installer $installer, ILogger $logger) { + parent::__construct(); + $this->manager = $manager; + $this->installer = $installer; + $this->logger = $logger; + } + + protected function configure() { + $this + ->setName('app:update') + ->setDescription('update an app or all apps') + ->addArgument( + 'app-id', + InputArgument::OPTIONAL, + 'update the specified app' + ) + ->addOption( + 'all', + null, + InputOption::VALUE_NONE, + 'update all updatable apps' + ) + ->addOption( + 'showonly', + null, + InputOption::VALUE_NONE, + 'show update(s) without updating' + ) + + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $singleAppId = $input->getArgument('app-id'); + + if ($singleAppId) { + $apps = array($singleAppId); + try { + $this->manager->getAppPath($singleAppId); + } catch (\OCP\App\AppPathNotFoundException $e) { + $output->writeln($singleAppId . ' not installed'); + return 1; + } + + } else if ($input->getOption('all') || $input->getOption('showonly')) { + $apps = \OC_App::getAllApps(); + } else { + $output->writeln("<error>Please specify an app to update or \"--all\" to update all updatable apps\"</error>"); + return 1; + } + + $return = 0; + foreach ($apps as $appId) { + $newVersion = $this->installer->isUpdateAvailable($appId); + if ($newVersion) { + $output->writeln($appId . ' new version available: ' . $newVersion); + + if (!$input->getOption('showonly')) { + try { + $result = $this->installer->updateAppstoreApp($appId); + } catch(\Exception $e) { + $this->logger->logException($e, ['message' => 'Failure during update of app "' . $appId . '"','app' => 'app:update']); + $output->writeln('Error: ' . $e->getMessage()); + $return = 1; + } + + if ($result === false) { + $output->writeln($appId . ' couldn\'t be updated'); + $return = 1; + } else if($result === true) { + $output->writeln($appId . ' updated'); + } + } + } + } + + return $return; + } +} + diff --git a/core/Command/Upgrade.php b/core/Command/Upgrade.php index 86f049d9f2a..5a2deea0b6c 100644 --- a/core/Command/Upgrade.php +++ b/core/Command/Upgrade.php @@ -99,8 +99,7 @@ class Upgrade extends Command { $this->config, \OC::$server->getIntegrityCodeChecker(), $this->logger, - $this->installer, - \OC::$server->getJobList() + $this->installer ); $dispatcher = \OC::$server->getEventDispatcher(); @@ -192,9 +191,6 @@ class Upgrade extends Command { $updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) { $output->writeln('<info>Maintenance mode is kept active</info>'); }); - $updater->listen('\OC\Updater', 'waitForCronToFinish', function () use($output) { - $output->writeln('<info>Waiting for cron to finish (checks again in 5 seconds) …</info>'); - }); $updater->listen('\OC\Updater', 'updateEnd', function ($success) use($output, $self) { if ($success) { diff --git a/core/Controller/ClientFlowLoginController.php b/core/Controller/ClientFlowLoginController.php index 088a6a98699..2e8216c2ba5 100644 --- a/core/Controller/ClientFlowLoginController.php +++ b/core/Controller/ClientFlowLoginController.php @@ -197,7 +197,7 @@ class ClientFlowLoginController extends Controller { 'instanceName' => $this->defaults->getName(), 'urlGenerator' => $this->urlGenerator, 'stateToken' => $stateToken, - 'serverHost' => $this->request->getServerHost(), + 'serverHost' => $this->getServerPath(), 'oauthState' => $this->session->get('oauth.state'), ], 'guest' @@ -235,7 +235,7 @@ class ClientFlowLoginController extends Controller { 'instanceName' => $this->defaults->getName(), 'urlGenerator' => $this->urlGenerator, 'stateToken' => $stateToken, - 'serverHost' => $this->request->getServerHost(), + 'serverHost' => $this->getServerPath(), 'oauthState' => $this->session->get('oauth.state'), ], 'guest' @@ -345,32 +345,34 @@ class ClientFlowLoginController extends Controller { ); $this->session->remove('oauth.state'); } else { - $serverPostfix = ''; + $redirectUri = 'nc://login/server:' . $this->getServerPath() . '&user:' . urlencode($loginName) . '&password:' . urlencode($token); - if (strpos($this->request->getRequestUri(), '/index.php') !== false) { - $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/index.php')); - } else if (strpos($this->request->getRequestUri(), '/login/flow') !== false) { - $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/login/flow')); - } + // Clear the token from the login here + $this->tokenProvider->invalidateToken($sessionId); + } - $protocol = $this->request->getServerProtocol(); + return new Http\RedirectResponse($redirectUri); + } - if ($protocol !== "https") { - $xForwardedProto = $this->request->getHeader('X-Forwarded-Proto'); - $xForwardedSSL = $this->request->getHeader('X-Forwarded-Ssl'); - if ($xForwardedProto === 'https' || $xForwardedSSL === 'on') { - $protocol = 'https'; - } - } + private function getServerPath(): string { + $serverPostfix = ''; + if (strpos($this->request->getRequestUri(), '/index.php') !== false) { + $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/index.php')); + } else if (strpos($this->request->getRequestUri(), '/login/flow') !== false) { + $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/login/flow')); + } - $serverPath = $protocol . "://" . $this->request->getServerHost() . $serverPostfix; - $redirectUri = 'nc://login/server:' . $serverPath . '&user:' . urlencode($loginName) . '&password:' . urlencode($token); + $protocol = $this->request->getServerProtocol(); - // Clear the token from the login here - $this->tokenProvider->invalidateToken($sessionId); + if ($protocol !== "https") { + $xForwardedProto = $this->request->getHeader('X-Forwarded-Proto'); + $xForwardedSSL = $this->request->getHeader('X-Forwarded-Ssl'); + if ($xForwardedProto === 'https' || $xForwardedSSL === 'on') { + $protocol = 'https'; + } } - return new Http\RedirectResponse($redirectUri); + return $protocol . "://" . $this->request->getServerHost() . $serverPostfix; } } diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php index a9fb22f21b7..d34f243f15f 100644 --- a/core/Controller/LoginController.php +++ b/core/Controller/LoginController.php @@ -171,6 +171,14 @@ class LoginController extends Controller { $parameters['loginName'] = ''; $parameters['user_autofocus'] = true; } + + $autocomplete = $this->config->getSystemValue('login_form_autocomplete', true); + if ($autocomplete){ + $parameters['login_form_autocomplete'] = 'on'; + } else { + $parameters['login_form_autocomplete'] = 'off'; + } + if (!empty($redirect_url)) { $parameters['redirect_url'] = $redirect_url; } diff --git a/core/Migrations/Version15000Date20181015062942.php b/core/Migrations/Version15000Date20181015062942.php new file mode 100644 index 00000000000..e73b663d2fd --- /dev/null +++ b/core/Migrations/Version15000Date20181015062942.php @@ -0,0 +1,54 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 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 OC\Core\Migrations; + +use Closure; +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +class Version15000Date20181015062942 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(); + + $table = $schema->getTable('share'); + $table->addColumn('hide_download', 'smallint', [ + 'notnull' => true, + 'length' => 1, + 'default' => 0, + ]); + + return $schema; + } +} diff --git a/core/Migrations/Version15000Date20181029084625.php b/core/Migrations/Version15000Date20181029084625.php new file mode 100644 index 00000000000..f3e12ddbb9b --- /dev/null +++ b/core/Migrations/Version15000Date20181029084625.php @@ -0,0 +1,53 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com) + * + * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> + * + * @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 OC\Core\Migrations; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +class Version15000Date20181029084625 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(); + + $table = $schema->getTable('share'); + $table->addColumn('label', 'string', [ + 'notnull' => false, + 'length' => 255, + ]); + + return $schema; + } + +} diff --git a/core/ajax/update.php b/core/ajax/update.php index 6def2c6797b..7dead22b9dd 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -119,8 +119,7 @@ if (\OCP\Util::needUpgrade()) { $config, \OC::$server->getIntegrityCodeChecker(), $logger, - \OC::$server->query(\OC\Installer::class), - \OC::$server->getJobList() + \OC::$server->query(\OC\Installer::class) ); $incompatibleApps = []; @@ -153,9 +152,6 @@ if (\OCP\Util::needUpgrade()) { $updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) { $eventSource->send('success', (string)$l->t('Maintenance mode is kept active')); }); - $updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds) …')); - }); $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) { $eventSource->send('success', (string)$l->t('Updating database schema')); }); diff --git a/core/css/apps.scss b/core/css/apps.scss index 8b94d08ce2e..b7afc19705d 100644 --- a/core/css/apps.scss +++ b/core/css/apps.scss @@ -781,27 +781,47 @@ kbd { /* TABS ------------------------------------------------------------ */ .tabHeaders { - display: inline-block; - margin: 15px; + display: flex; + margin-bottom: 16px; + .tabHeader { - float: left; - padding: 12px; + display: flex; + flex-direction: column; + flex-grow: 1; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; cursor: pointer; color: var(--color-text-lighter); margin-bottom: 1px; + padding: 5px; + + /* Use same amount as sidebar padding */ + &:first-child { + padding-left: 15px; + } + &:last-child { + padding-right: 15px; + } + .icon { display: inline-block; - width: 16px; + width: 100%; height: 16px; background-size: 16px; vertical-align: middle; margin-top: -2px; margin-right: 3px; opacity: .7; + cursor: pointer; } + a { color: var(--color-text-lighter); margin-bottom: 1px; + overflow: hidden; + text-overflow: ellipsis; } &.selected { font-weight: bold; @@ -1250,7 +1270,9 @@ $popovericon-size: 16px; position: relative; .popovermenu { margin: 0; - right: -5px; + // action icon have -7px margin + // default popover is normally 5px + right: -2px; } } } diff --git a/core/css/css-variables.scss b/core/css/css-variables.scss index a2946672294..6df2e0a3428 100644 --- a/core/css/css-variables.scss +++ b/core/css/css-variables.scss @@ -39,4 +39,6 @@ --border-radius-pill: $border-radius-pill; --font-face: $font-face; + + --animation-quick: $animation-quick; } diff --git a/core/css/header.scss b/core/css/header.scss index f2527ca3a79..30f2c30b7b4 100644 --- a/core/css/header.scss +++ b/core/css/header.scss @@ -513,25 +513,92 @@ nav[role='navigation'] { height: 20px; } - /* app title popup */ + /* App title */ li span { - display: none; + opacity: 0; position: absolute; - overflow: visible; - background-color: var(--color-main-background); - white-space: nowrap; - border: none; - border-radius: var(--border-radius); - border-top-left-radius: 0; - border-top-right-radius: 0; - color: var(--color-text-lighter); - width: auto; - left: 50%; - top: 100%; - transform: translateX(-50%); - padding: 4px 10px; - filter: drop-shadow(0 1px 10px var(--color-box-shadow)); - z-index: 100; + color: var(--color-primary-text); + bottom: -5px; + width: 100%; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + } + + + /* Set up transitions for showing app titles on hover */ + li { + /* Prevent flicker effect because of low-hanging span element */ + overflow-y: hidden; + + /* App icon */ + svg, + .icon-more-white { + transition: transform var(--animation-quick) ease; + } + + /* App title */ + span { + transition: all var(--animation-quick) ease; + } + + /* Triangle */ + a::before { + transition: border var(--animation-quick) ease; + } + } + + /* Show all app titles on hovering app menu area */ + &:hover { + li { + /* Move up app icon */ + svg, + .icon-more, icon-more-white, + .icon-loading-small, .icon-loading-small-dark { + transform: translateY(-7px); + } + + /* Show app title */ + span { + opacity: .6; + bottom: 2px; + z-index: -1; /* fix clickability issue - otherwise we need to move the span into the link */ + } + + /* Prominent app title for current and hovered/focused app */ + &:hover span, + &:focus span, + .active + span { + opacity: 1; + } + + /* Smaller triangle because of limited space */ + a::before { + border-width: 5px; + } + } + } + + /* Also show app title on focusing single entry (showing all on focus is only possible with CSS4 and parent selectors) */ + li a:focus { + /* Move up app icon */ + svg, + .icon-more, icon-more-white, + .icon-loading-small, .icon-loading-small-dark { + transform: translateY(-7px); + } + + /* Show app title */ + & + span, + span { + opacity: 1; + bottom: 2px; + } + + /* Smaller triangle because of limited space */ + &::before { + border-width: 5px; + } } /* show triangle below active app */ @@ -549,6 +616,7 @@ nav[role='navigation'] { bottom: 0; display: none; } + /* triangle focus feedback */ li a.active::before, li:hover a::before, @@ -560,7 +628,6 @@ nav[role='navigation'] { z-index: 99; } li:hover a::before, - li:hover a::before, li a.active:hover::before, li a:focus::before { z-index: 101; diff --git a/core/css/icons.scss b/core/css/icons.scss index 5b96d1223a7..99b1dc9c215 100644 --- a/core/css/icons.scss +++ b/core/css/icons.scss @@ -466,3 +466,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] @include icon-color('search', 'actions', $color-black, 1, true); } + +.icon-talk { + @include icon-color('app-dark', 'spreed', $color-black, 1); +} diff --git a/core/css/jquery-ui-fixes.scss b/core/css/jquery-ui-fixes.scss index e30beee44e5..eab22e70d62 100644 --- a/core/css/jquery-ui-fixes.scss +++ b/core/css/jquery-ui-fixes.scss @@ -70,7 +70,8 @@ .ui-widget-header .ui-state-highlight { border: 1px solid var(--color-main-background); background: var(--color-main-background) none; - color: var(--color-text-lighter); + color: var(--color-text-light); + font-weight: 600; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a, @@ -171,9 +172,12 @@ &.ui-menu { padding: 0; .ui-menu-item a { + color: var(--color-text-lighter); + padding: 4px 4px 4px 14px; + &.ui-state-focus, &.ui-state-active { - font-weight: inherit; box-shadow: inset 4px 0 var(--color-primary); + color: var(--color-text); } } } diff --git a/core/css/styles.scss b/core/css/styles.scss index 4b80b4f9626..f23f4c2dead 100644 --- a/core/css/styles.scss +++ b/core/css/styles.scss @@ -798,7 +798,7 @@ code { &.view-grid { $grid-size: 120px; $grid-pad: 10px; - $name-height: 20px; + $name-height: 30px; display: flex; flex-direction: column; @@ -818,20 +818,22 @@ code { flex-direction: column; width: $grid-size - 2 * $grid-pad; + td { border: none; padding: 0; + text-align: center; + border-radius: var(--border-radius); &.filename { padding: #{$grid-size - 2 * $grid-pad} 0 0 0; background-position: center top; background-size: contain; line-height: $name-height; - height: $name-height; } &.filesize { - line-height: $name-height; - text-align: left; + line-height: $name-height / 3; + width: 100%; } &.date { display: none; diff --git a/core/css/variables.scss b/core/css/variables.scss index dffd6403471..a827629479c 100644 --- a/core/css/variables.scss +++ b/core/css/variables.scss @@ -80,6 +80,7 @@ $border-radius-pill: 100px !default; $font-face: 'Nunito', 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif !default; +$animation-quick: 100ms; // various structure data $header-height: 50px; diff --git a/core/js/js.js b/core/js/js.js index fd6e0a68da5..026cc6bb0d6 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1562,13 +1562,14 @@ function initCore() { var resizeMenu = function() { var appList = $('#appmenu li'); - var headerWidth = $('.header-left').outerWidth() - $('#nextcloud').outerWidth(); + var rightHeaderWidth = $('.header-right').outerWidth(); + var headerWidth = $('header').outerWidth(); var usePercentualAppMenuLimit = 0.33; var minAppsDesktop = 8; - var availableWidth = headerWidth - $(appList).width(); + var availableWidth = headerWidth - $('#nextcloud').outerWidth() - (rightHeaderWidth > 210 ? rightHeaderWidth : 210) var isMobile = $(window).width() < 768; if (!isMobile) { - availableWidth = headerWidth * usePercentualAppMenuLimit; + availableWidth = availableWidth * usePercentualAppMenuLimit; } var appCount = Math.floor((availableWidth / $(appList).width())); if (isMobile && appCount > minAppsDesktop) { @@ -1613,7 +1614,7 @@ function initCore() { } }; $(window).resize(resizeMenu); - resizeMenu(); + setTimeout(resizeMenu, 0); // just add snapper for logged in users if($('#app-navigation').length && !$('html').hasClass('lte9')) { diff --git a/core/js/share/sharedialoglinkshareview.handlebars b/core/js/share/sharedialoglinkshareview.handlebars index bc7051683a2..64f52704290 100644 --- a/core/js/share/sharedialoglinkshareview.handlebars +++ b/core/js/share/sharedialoglinkshareview.handlebars @@ -1,25 +1,39 @@ {{#if shareAllowed}} -<ul id="shareLink" class="shareWithList"> - <li data-share-id="{{cid}}"> - <div class="avatar icon-public-white"></div><span class="username" title="{{linkShareLabel}}">{{linkShareLabel}}</span> - <span class="sharingOptionsGroup"> - <span class="shareOption"> - <span class="icon-loading-small hidden"></span> - <input id="linkCheckbox-{{cid}}" {{#if isLinkShare}}checked="checked"{{/if}} type="checkbox" name="linkCheckbox" class="linkCheckbox permissions checkbox"> - <label for="linkCheckbox-{{cid}}">{{linkShareEnableLabel}}</label> +<ul class="shareWithList"> + {{#if nolinkShares}} + <li data-share-id="new-share"> + <div class="avatar icon-public-white"></div> + <span class="username">{{newShareLabel}}</span> + <span class="sharingOptionsGroup"> + <div class="share-menu"> + <a href="#" class="icon icon-add new-share has-tooltip {{#if showPending}}hidden{{/if}}" title="{{newShareTitle}}"></a> + <span class="icon icon-loading-small {{#unless showPending}}hidden{{/unless}}"></span> + {{#if showPending}} + {{{pendingPopoverMenu}}} + {{/if}} + </div> </span> - {{#if showMenu}} - <div class="share-menu" tabindex="0"><span class="icon icon-more"></span> + </li> + {{/if}} + {{#each linkShares}} + <li data-share-id="{{cid}}"> + <div class="avatar icon-public-white"></div><span class="username" title="{{linkShareLabel}}">{{linkShareLabel}}</span> + + <span class="sharingOptionsGroup"> + <a href="#" class="clipboard-button icon icon-clippy has-tooltip" data-clipboard-text="{{shareLinkURL}}" title="{{copyLabel}}"></a> + <div class="share-menu"> + <a href="#" class="icon icon-more {{#if showPending}}hidden{{/if}}"></a> + <span class="icon icon-loading-small {{#unless showPending}}hidden{{/unless}}"></span> {{#if showPending}} {{{pendingPopoverMenu}}} {{else}} {{{popoverMenu}}} {{/if}} </div> - {{/if}} - </span> - </li> + </span> + </li> + {{/each}} </ul> {{else}} -{{#if noSharingPlaceholder}}<input id="shareWith-{{cid}}" class="shareWithField" type="text" placeholder="{{noSharingPlaceholder}}" disabled="disabled"/>{{/if}} +{{#if noSharingPlaceholder}}<input id="shareWith-{{cid}}" class="shareWithField" type="text" placeholder="{{noSharingPlaceholder}}" disabled="disabled" />{{/if}} {{/if}} diff --git a/core/js/share/sharedialoglinkshareview_popover_menu.handlebars b/core/js/share/sharedialoglinkshareview_popover_menu.handlebars index 412ed8efca0..59312bc70b0 100644 --- a/core/js/share/sharedialoglinkshareview_popover_menu.handlebars +++ b/core/js/share/sharedialoglinkshareview_popover_menu.handlebars @@ -1,11 +1,5 @@ <div class="popovermenu menu"> <ul> - <li> - <a href="#" class="menuitem clipboardButton" data-clipboard-text="{{shareLinkURL}}"> - <span class="icon icon-clippy" ></span> - <span>{{copyLabel}}</span> - </a> - </li> <li class="hidden linkTextMenu"> <span class="menuitem icon-link-text"> <input id="linkText-{{cid}}" class="linkText" type="text" readonly="readonly" value="{{shareLinkURL}}" /> @@ -13,20 +7,21 @@ </li> {{#if publicUpload}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <span class="icon-loading-small hidden"></span> <input type="radio" name="publicUpload" value="{{publicUploadRValue}}" id="sharingDialogAllowPublicUpload-r-{{cid}}" class="radio publicUploadRadio" {{{publicUploadRChecked}}} /> <label for="sharingDialogAllowPublicUpload-r-{{cid}}">{{publicUploadRLabel}}</label> </span> </li> <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <span class="icon-loading-small hidden"></span> <input type="radio" name="publicUpload" value="{{publicUploadRWValue}}" id="sharingDialogAllowPublicUpload-rw-{{cid}}" class="radio publicUploadRadio" {{{publicUploadRWChecked}}} /> <label for="sharingDialogAllowPublicUpload-rw-{{cid}}">{{publicUploadRWLabel}}</label> - </span></li> + </span> + </li> <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <span class="icon-loading-small hidden"></span> <input type="radio" name="publicUpload" value="{{publicUploadWValue}}" id="sharingDialogAllowPublicUpload-w-{{cid}}" class="radio publicUploadRadio" {{{publicUploadWChecked}}} /> <label for="sharingDialogAllowPublicUpload-w-{{cid}}">{{publicUploadWLabel}}</label> @@ -35,39 +30,62 @@ {{/if}} {{#if publicEditing}} <li id="allowPublicEditingWrapper"> - <span class="shareOption menuitem"> + <span class="menuitem"> <span class="icon-loading-small hidden"></span> <input type="checkbox" name="allowPublicEditing" id="sharingDialogAllowPublicEditing-{{cid}}" class="checkbox publicEditingCheckbox" {{{publicEditingChecked}}} /> <label for="sharingDialogAllowPublicEditing-{{cid}}">{{publicEditingLabel}}</label> </span> </li> {{/if}} + {{#if showHideDownloadCheckbox}} + <li> + <span class="menuitem"> + <span class="icon-loading-small hidden"></span> + <input type="checkbox" name="hideDownload" id="sharingDialogHideDownload-{{cid}}" class="checkbox hideDownloadCheckbox" + {{#if hideDownload}}checked="checked"{{/if}} /> + <label for="sharingDialogHideDownload-{{cid}}">{{hideDownloadLabel}}</label> + </span> + </li> + {{/if}} {{#if showPasswordCheckBox}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} {{#if isPasswordEnforced}}disabled="disabled"{{/if}} value="1" /> <label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label> </span> </li> <li class="{{#unless isPasswordSet}}hidden{{/unless}} linkPassMenu"> - <span class="shareOption menuitem icon-share-pass"> + <span class="menuitem icon-share-pass"> <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" autocomplete="new-password" /> <span class="icon icon-loading-small hidden"></span> </span> </li> {{/if}} + {{#if showPasswordByTalkCheckBox}} + <li> + <span class="shareOption menuitem"> + <span class="icon-loading-small hidden"></span> + <input type="checkbox" name="passwordByTalk" id="passwordByTalk-{{cid}}" class="checkbox passwordByTalkCheckbox" + {{#if isPasswordByTalkSet}}checked="checked"{{/if}} /> + <label for="passwordByTalk-{{cid}}">{{passwordByTalkLabel}}</label> + </span> + </li> + {{/if}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="expireDate-{{cid}}" type="checkbox" name="expirationDate" class="expireDate checkbox" - {{#if hasExpireDate}}checked="checked"{{/if}} {{#if isExpirationEnforced}}disabled="disabled"{{/if}}" /> + {{#if hasExpireDate}}checked="checked"{{/if}} {{#if isExpirationEnforced}}disabled="disabled"{{/if}} /> <label for="expireDate-{{cid}}">{{expireDateLabel}}</label> </span> </li> <li class="{{#unless hasExpireDate}}hidden{{/unless}}"> <span class="menuitem icon-expiredate expirationDateContainer-{{cid}}"> <label for="expirationDatePicker-{{cid}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label> - <input id="expirationDatePicker-{{cid}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" /> + <!-- do not use the datepicker if enforced --> + <input id="expirationDatePicker-{{cid}}" class="{{#unless isExpirationEnforced}}datepicker{{/unless}}" type="text" + placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" + data-max-date="{{maxDate}}" {{#if isExpirationEnforced}}readonly{{/if}} /> </span> </li> <li> @@ -75,22 +93,32 @@ <span class="icon-loading-small hidden"></span> <span class="icon icon-edit"></span> <span>{{addNoteLabel}}</span> - <input type="button" class="share-note-delete icon-delete"> + <input type="button" class="share-note-delete icon-delete {{#unless hasNote}}hidden{{/unless}}"> </a> </li> - <li class="share-note-form share-note-link hidden"> + <li class="share-note-form share-note-link {{#unless hasNote}}hidden{{/unless}}"> <span class="menuitem icon-note"> <textarea class="share-note">{{shareNote}}</textarea> <input type="submit" class="icon-confirm share-note-submit" value="" id="add-note-{{shareId}}" /> - </span> + </span> </li> {{#each social}} <li> - <a href="#" class="shareOption menuitem pop-up" data-url="{{url}}" data-window="{{newWindow}}"> + <a href="#" class="menuitem pop-up" data-url="{{url}}" data-window="{{newWindow}}"> <span class="icon {{iconClass}}"></span> <span>{{label}}</span> </a> </li> {{/each}} + <li> + <a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLinkLabel}}</span></a> + </li> + <li> + <a href="#" class="new-share"> + <span class="icon-loading-small hidden"></span> + <span class="icon icon-add"></span> + <span>{{newShareLabel}}</span> + </a> + </li> </ul> </div> diff --git a/core/js/share/sharedialoglinkshareview_popover_menu_pending.handlebars b/core/js/share/sharedialoglinkshareview_popover_menu_pending.handlebars index e39c082315b..787f50c6c1e 100644 --- a/core/js/share/sharedialoglinkshareview_popover_menu_pending.handlebars +++ b/core/js/share/sharedialoglinkshareview_popover_menu_pending.handlebars @@ -1,14 +1,20 @@ -<div class="popovermenu pendingpopover menu"> +<div class="popovermenu open menu"> <ul> {{#if isPasswordEnforced}} - <li><span class="shareOption menuitem"> - <input type="checkbox" name="showPassword" id="showPassword-{{cid}}" checked="checked" disabled class="checkbox showPasswordCheckbox" value="1" /> - <label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label> - </span></li> - <li class="linkPassMenu"><span class="shareOption menuitem icon-share-pass"> - <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" autocomplete="new-password" /> - <span class="icon icon-loading-small hidden"></span> - </span></li> + <li> + <span class="menuitem icon-info"> + <p>{{enforcedPasswordLabel}}</p> + </span> + </li> + <li class="linkPassMenu"> + <span class="menuitem"> + <form autocomplete="off" class="enforcedPassForm"> + <input id="enforcedPassText" required class="enforcedPassText" type="password" + placeholder="{{passwordPlaceholder}}" autocomplete="enforcedPassText" minlength="{{minPasswordLength}}" /> + <input type="submit" value=" " class="primary icon-checkmark-white"> + </form> + </span> + </li> {{/if}} </ul> </div> diff --git a/core/js/share/sharedialogshareelistview.handlebars b/core/js/share/sharedialogshareelistview.handlebars index a95949c8157..92c07f80290 100644 --- a/core/js/share/sharedialogshareelistview.handlebars +++ b/core/js/share/sharedialogshareelistview.handlebars @@ -5,7 +5,7 @@ <span class="username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span> <span class="sharingOptionsGroup"> {{#if editPermissionPossible}} - <span class="shareOption"> + <span> <input id="canEdit-{{cid}}-{{shareId}}" type="checkbox" name="edit" class="permissions checkbox" /> <label for="canEdit-{{cid}}-{{shareId}}">{{canEditLabel}}</label> </span> @@ -15,7 +15,7 @@ </div> </span> </li> - {{/each}} + {{/each}} {{#each linkReshares}} <li data-share-id="{{shareId}}" data-share-type="{{shareType}}"> <div class="avatar" data-username="{{shareInitiator}}"></div> diff --git a/core/js/share/sharedialogshareelistview_popover_menu.handlebars b/core/js/share/sharedialogshareelistview_popover_menu.handlebars index c135d31b081..64fe51a3d24 100644 --- a/core/js/share/sharedialogshareelistview_popover_menu.handlebars +++ b/core/js/share/sharedialogshareelistview_popover_menu.handlebars @@ -2,7 +2,7 @@ <ul> {{#if isResharingAllowed}} {{#if sharePermissionPossible}} {{#unless isMailShare}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="canShare-{{cid}}-{{shareId}}" type="checkbox" name="share" class="permissions checkbox" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" /> <label for="canShare-{{cid}}-{{shareId}}">{{canShareLabel}}</label> </span> @@ -11,7 +11,7 @@ {{#if isFolder}} {{#if createPermissionPossible}}{{#unless isMailShare}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="canCreate-{{cid}}-{{shareId}}" type="checkbox" name="create" class="permissions checkbox" {{#if hasCreatePermission}}checked="checked"{{/if}} data-permissions="{{createPermission}}"/> <label for="canCreate-{{cid}}-{{shareId}}">{{createPermissionLabel}}</label> </span> @@ -19,7 +19,7 @@ {{/unless}}{{/if}} {{#if updatePermissionPossible}}{{#unless isMailShare}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="canUpdate-{{cid}}-{{shareId}}" type="checkbox" name="update" class="permissions checkbox" {{#if hasUpdatePermission}}checked="checked"{{/if}} data-permissions="{{updatePermission}}"/> <label for="canUpdate-{{cid}}-{{shareId}}">{{updatePermissionLabel}}</label> </span> @@ -27,7 +27,7 @@ {{/unless}}{{/if}} {{#if deletePermissionPossible}}{{#unless isMailShare}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="canDelete-{{cid}}-{{shareId}}" type="checkbox" name="delete" class="permissions checkbox" {{#if hasDeletePermission}}checked="checked"{{/if}} data-permissions="{{deletePermission}}"/> <label for="canDelete-{{cid}}-{{shareId}}">{{deletePermissionLabel}}</label> </span> @@ -37,14 +37,14 @@ {{#if isMailShare}} {{#if hasCreatePermission}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="secureDrop-{{cid}}-{{shareId}}" type="checkbox" name="secureDrop" class="checkbox secureDrop" {{#if secureDropMode}}checked="checked"{{/if}} data-permissions="{{readPermission}}"/> <label for="secureDrop-{{cid}}-{{shareId}}">{{secureDropLabel}}</label> </span> </li> {{/if}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="password-{{cid}}-{{shareId}}" type="checkbox" name="password" class="password checkbox" {{#if isPasswordSet}}checked="checked"{{/if}}{{#if isPasswordSet}}{{#if isPasswordForMailSharesRequired}}disabled=""{{/if}}{{/if}}" /> <label for="password-{{cid}}-{{shareId}}">{{passwordLabel}}</label> </span> @@ -58,7 +58,7 @@ </li> {{#if isTalkEnabled}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="passwordByTalk-{{cid}}-{{shareId}}" type="checkbox" name="passwordByTalk" class="passwordByTalk checkbox" {{#if isPasswordByTalkSet}}checked="checked"{{/if}} /> <label for="passwordByTalk-{{cid}}-{{shareId}}">{{passwordByTalkLabel}}</label> </span> @@ -73,7 +73,7 @@ {{/if}} {{/if}} <li> - <span class="shareOption menuitem"> + <span class="menuitem"> <input id="expireDate-{{cid}}-{{shareId}}" type="checkbox" name="expirationDate" class="expireDate checkbox" {{#if hasExpireDate}}checked="checked"{{/if}}" /> <label for="expireDate-{{cid}}-{{shareId}}">{{expireDateLabel}}</label> </span> @@ -86,13 +86,14 @@ </li> {{#if isNoteAvailable}} <li> - <a href="#" class="share-add"><span class="icon-loading-small hidden"></span> + <a href="#" class="share-add"> + <span class="icon-loading-small hidden"></span> <span class="icon icon-edit"></span> <span>{{addNoteLabel}}</span> - <input type="button" class="share-note-delete icon-delete"> + <input type="button" class="share-note-delete icon-delete {{#unless hasNote}}hidden{{/unless}}"> </a> </li> - <li class="share-note-form hidden"> + <li class="share-note-form {{#unless hasNote}}hidden{{/unless}}"> <span class="menuitem icon-note"> <textarea class="share-note">{{shareNote}}</textarea> <input type="submit" class="icon-confirm share-note-submit" value="" id="add-note-{{shareId}}" /> diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index aac4843c8e0..e5af4ad1f17 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -42,15 +42,19 @@ /** @type {boolean} **/ showPending: false, + /** @type {string} **/ + password: '', + events: { - // enable/disable - 'change .linkCheckbox': 'onLinkCheckBoxChange', // open menu 'click .share-menu .icon-more': 'onToggleMenu', + // hide download + 'change .hideDownloadCheckbox': 'onHideDownloadChange', // password 'focusout input.linkPassText': 'onPasswordEntered', 'keyup input.linkPassText': 'onPasswordKeyUp', 'change .showPasswordCheckbox': 'onShowPasswordClick', + 'change .passwordByTalkCheckbox': 'onPasswordByTalkChange', 'change .publicEditingCheckbox': 'onAllowPublicEditingChange', // copy link url 'click .linkText': 'onLinkTextClick', @@ -65,7 +69,13 @@ // note 'click .share-add': 'showNoteForm', 'click .share-note-delete': 'deleteNote', - 'click .share-note-submit': 'updateNote' + 'click .share-note-submit': 'updateNote', + // remove + 'click .unshare': 'onUnshare', + // new share + 'click .new-share': 'newShare', + // enforced pass set + 'submit .enforcedPassForm': 'enforcedPasswordSet', }, initialize: function(options) { @@ -87,8 +97,35 @@ view.render(); }); - this.model.on('change:linkShare', function() { - view.render(); + this.model.on('change:linkShares', function(model, linkShares) { + // The "Password protect by Talk" item is shown only when there + // is a password. Unfortunately there is no fine grained + // rendering of items in the link shares, so the whole view + // needs to be rendered again when the password of a share + // changes. + // Note that this event handler is concerned only about password + // changes; other changes in the link shares does not trigger + // a rendering, so the view must be rendered again as needed in + // those cases (for example, when a link share is removed). + + var previousLinkShares = model.previous('linkShares'); + if (previousLinkShares.length !== linkShares.length) { + return; + } + + var i; + for (i = 0; i < linkShares.length; i++) { + if (linkShares[i].id !== previousLinkShares[i].id) { + // A resorting should never happen, but just in case. + return; + } + + if (linkShares[i].password !== previousLinkShares[i].password) { + view.render(); + + return; + } + } }); if(!_.isUndefined(options.configModel)) { @@ -97,26 +134,33 @@ throw 'missing OC.Share.ShareConfigModel'; } - var clipboard = new Clipboard('.clipboardButton'); + var clipboard = new Clipboard('.clipboard-button'); clipboard.on('success', function(e) { - var $menu = $(e.trigger); - var $linkTextMenu = $menu.parent().next('li.linkTextMenu') + var $trigger = $(e.trigger); - $menu.tooltip('hide') + $trigger.tooltip('hide') .attr('data-original-title', t('core', 'Copied!')) .tooltip('fixTitle') .tooltip({placement: 'bottom', trigger: 'manual'}) .tooltip('show'); _.delay(function() { - $menu.tooltip('hide'); - $menu.tooltip('destroy'); + $trigger.tooltip('hide') + .attr('data-original-title', t('core', 'Copy link')) + .tooltip('fixTitle') }, 3000); }); clipboard.on('error', function (e) { - var $menu = $(e.trigger); - var $linkTextMenu = $menu.parent().next('li.linkTextMenu'); + var $trigger = $(e.trigger); + var $menu = $trigger.next('.share-menu').find('.popovermenu'); + var $linkTextMenu = $menu.find('li.linkTextMenu'); var $input = $linkTextMenu.find('.linkText'); + var $li = $trigger.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + + // show menu + OC.showMenu(null, $menu); + var actionMsg = ''; if (/iPhone|iPad/i.test(navigator.userAgent)) { actionMsg = t('core', 'Not supported!'); @@ -141,75 +185,161 @@ }); }, - onLinkCheckBoxChange: function() { - var $checkBox = this.$el.find('.linkCheckbox'); - var $loading = $checkBox.siblings('.icon-loading-small'); - if(!$loading.hasClass('hidden')) { + newShare: function(event) { + var self = this; + var $target = $(event.target); + var $li = $target.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $loading = $li.find('.share-menu > .icon-loading-small'); + + if(!$loading.hasClass('hidden') && this.password === '') { + // in process return false; } - if($checkBox.is(':checked')) { - if(this.configModel.get('enforcePasswordForPublicLink') === false) { - $loading.removeClass('hidden'); - // this will create it - this.model.saveLinkShare(); - $('.share-menu .icon-more').click(); - $('.share-menu .icon-more + .popovermenu .clipboardButton').click(); - } else { - // force the rendering of the menu - this.showPending = true; - this.render() - $('.share-menu .icon-more').click(); - $('.share-menu .icon-more + .popovermenu input:eq(1)').focus() - } + // hide all icons and show loading + $li.find('.icon').addClass('hidden'); + $loading.removeClass('hidden'); + + // hide menu + OC.hideMenus(); + + var shareData = {} + + var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); + var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); + + // set default expire date + if (isExpirationEnforced) { + var defaultExpireDays = this.configModel.get('defaultExpireDate'); + var expireDate = moment().add(defaultExpireDays, 'day').format('DD-MM-YYYY') + shareData.expireDate = expireDate; + } + + // if password is set, add to data + if (isPasswordEnforced && this.password !== '') { + shareData.password = this.password + } + + var newShareId = false; + + // We need a password before the share creation + if (isPasswordEnforced && !this.showPending && this.password === '') { + this.showPending = shareId; + this.render(); + $li.find('#enforcedPassText').focus(); } else { - if (this.model.get('linkShare').isLinkShare) { - $loading.removeClass('hidden'); - this.model.removeLinkShare(); - } else { - this.showPending = false; - this.render() - } + // else, we have a password or it is not enforced + $.when(this.model.saveLinkShare(shareData, { + success: function() { + $loading.addClass('hidden'); + $li.find('.icon').removeClass('hidden'); + self.render(); + // open the menu by default + // we can only do that after the render + if (newShareId) { + var shares = self.$el.find('li[data-share-id]'); + var $newShare = self.$el.find('li[data-share-id="'+newShareId+'"]'); + // only open the menu by default if this is the first share + if ($newShare && shares.length === 1) { + $menu = $newShare.find('.popovermenu'); + OC.showMenu(null, $menu); + } + } + }, + error: function() { + OC.Notification.showTemporary(t('core', 'Unable to create a link share')); + $loading.addClass('hidden'); + $li.find('.icon').removeClass('hidden'); + } + })).then(function(response) { + // resolve before success + newShareId = response.ocs.data.id + }); } }, - onLinkTextClick: function() { - var $el = this.$el.find('.linkText'); + enforcedPasswordSet: function(event) { + event.preventDefault(); + var $form = $(event.target); + var $input = $form.find('input.enforcedPassText'); + this.password = $input.val(); + this.showPending = false; + this.newShare(event); + }, + + onLinkTextClick: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var $el = $li.find('.linkText'); $el.focus(); $el.select(); }, - onShowPasswordClick: function() { - this.$el.find('.linkPass').slideToggle(OC.menuSpeed); - this.$el.find('.linkPassMenu').toggleClass('hidden'); - if(!this.$el.find('.showPasswordCheckbox').is(':checked')) { + onHideDownloadChange: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $checkbox = $li.find('.hideDownloadCheckbox'); + $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); + + var hideDownload = false; + if($checkbox.is(':checked')) { + hideDownload = true; + } + + this.model.saveLinkShare({ + hideDownload: hideDownload, + cid: shareId + }, { + success: function() { + $checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); + }, + error: function(obj, msg) { + OC.Notification.showTemporary(t('core', 'Unable to toggle this option')); + $checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); + } + }); + }, + + onShowPasswordClick: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + $li.find('.linkPass').slideToggle(OC.menuSpeed); + $li.find('.linkPassMenu').toggleClass('hidden'); + if(!$li.find('.showPasswordCheckbox').is(':checked')) { this.model.saveLinkShare({ - password: '' + password: '', + cid: shareId }); } else { if (!OC.Util.isIE()) { - this.$el.find('.linkPassText').focus(); + $li.find('.linkPassText').focus(); } } }, onPasswordKeyUp: function(event) { if(event.keyCode === 13) { - this.onPasswordEntered(); + this.onPasswordEntered(event); } }, - onPasswordEntered: function() { - var $loading = this.$el.find('.linkPassMenu .icon-loading-small'); + onPasswordEntered: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $loading = $li.find('.linkPassMenu .icon-loading-small'); if (!$loading.hasClass('hidden')) { // still in process return; } - var $input = this.$el.find('.linkPassText'); + var $input = $li.find('.linkPassText'); $input.removeClass('error'); var password = $input.val(); - if (this.$el.find('.linkPassText').attr('placeholder') === PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL) { + if ($li.find('.linkPassText').attr('placeholder') === PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL) { // in IE9 the password might be the placeholder due to bugs in the placeholders polyfill if(password === PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL) { @@ -228,7 +358,8 @@ .addClass('inlineblock'); this.model.saveLinkShare({ - password: password + password: password, + cid: shareId }, { complete: function(model) { $loading.removeClass('inlineblock').addClass('hidden'); @@ -244,8 +375,37 @@ }); }, - onAllowPublicEditingChange: function() { - var $checkbox = this.$('.publicEditingCheckbox'); + onPasswordByTalkChange: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $checkbox = $li.find('.passwordByTalkCheckbox'); + $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); + + var sendPasswordByTalk = false; + if($checkbox.is(':checked')) { + sendPasswordByTalk = true; + } + + this.model.saveLinkShare({ + sendPasswordByTalk: sendPasswordByTalk, + cid: shareId + }, { + success: function() { + $checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); + }, + error: function(obj, msg) { + OC.Notification.showTemporary(t('core', 'Unable to toggle this option')); + $checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); + } + }); + }, + + onAllowPublicEditingChange: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $checkbox = $li.find('.publicEditingCheckbox'); $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); var permissions = OC.PERMISSION_READ; @@ -254,15 +414,28 @@ } this.model.saveLinkShare({ - permissions: permissions + permissions: permissions, + cid: shareId + }, { + success: function() { + $checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); + }, + error: function(obj, msg) { + OC.Notification.showTemporary(t('core', 'Unable to toggle this option')); + $checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); + } }); }, - onPublicUploadChange: function(e) { - var permissions = e.currentTarget.value; + onPublicUploadChange: function(event) { + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var permissions = event.currentTarget.value; this.model.saveLinkShare({ - permissions: permissions + permissions: permissions, + cid: shareId }); }, @@ -276,7 +449,7 @@ var $form = $menu.next('li.share-note-form'); // show elements - $menu.find('.share-note-delete').toggle(); + $menu.find('.share-note-delete').toggleClass('hidden'); $form.toggleClass('hidden'); $form.find('textarea').focus(); }, @@ -294,7 +467,7 @@ $form.find('.share-note').val(''); $form.addClass('hidden'); - $menu.find('.share-note-delete').hide(); + $menu.find('.share-note-delete').addClass('hidden'); self.sendNote('', shareId, $menu); }, @@ -349,6 +522,11 @@ }, render: function() { + this.$el.find('.has-tooltip').tooltip(); + + // reset previously set passwords + this.password = ''; + var linkShareTemplate = this.template(); var resharingAllowed = this.model.sharePermissionPossible(); @@ -370,43 +548,21 @@ && this.model.createPermissionPossible() && this.configModel.isPublicUploadEnabled(); - var publicUploadRWChecked = ''; - var publicUploadRChecked = ''; - var publicUploadWChecked = ''; - - switch (this.model.linkSharePermissions()) { - case OC.PERMISSION_READ: - publicUploadRChecked = 'checked'; - break; - case OC.PERMISSION_CREATE: - publicUploadWChecked = 'checked'; - break; - case OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE: - publicUploadRWChecked = 'checked'; - break; - } var publicEditingChecked = ''; if(this.model.isPublicEditingAllowed()) { publicEditingChecked = 'checked="checked"'; } - var isLinkShare = this.model.get('linkShare').isLinkShare; - var isPasswordSet = !!this.model.get('linkShare').password; var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; - var showPasswordCheckBox = isLinkShare - && ( !this.configModel.get('enforcePasswordForPublicLink') - || !this.model.get('linkShare').password); var passwordPlaceholderInitial = this.configModel.get('enforcePasswordForPublicLink') ? PASSWORD_PLACEHOLDER_MESSAGE : PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL; var publicEditable = !this.model.isFolder() - && isLinkShare && this.model.updatePermissionPossible(); - var link = this.model.get('linkShare').link; var social = []; OC.Share.Social.Collection.each(function(model) { var url = model.get('url'); @@ -420,57 +576,33 @@ newWindow: model.get('newWindow') }); }); - - var defaultExpireDays = this.configModel.get('defaultExpireDate'); var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); - var hasExpireDate = !!this.model.get('linkShare').expiration || isExpirationEnforced; - - var expireDate; - if (hasExpireDate) { - expireDate = moment(this.model.get('linkShare').expiration, 'YYYY-MM-DD').format('DD-MM-YYYY'); - } // what if there is another date picker on that page? var minDate = new Date(); - var maxDate = null; // min date should always be the next day minDate.setDate(minDate.getDate()+1); - if(hasExpireDate) { - if(isExpirationEnforced) { - // TODO: hack: backend returns string instead of integer - var shareTime = this.model.get('linkShare').stime; - if (_.isNumber(shareTime)) { - shareTime = new Date(shareTime * 1000); - } - if (!shareTime) { - shareTime = new Date(); // now - } - shareTime = OC.Util.stripTime(shareTime).getTime(); - maxDate = new Date(shareTime + defaultExpireDays * 24 * 3600 * 1000); - } - } $.datepicker.setDefaults({ - minDate: minDate, - maxDate: maxDate + minDate: minDate }); this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'}); - var popover = this.popoverMenuTemplate({ - cid: this.model.get('linkShare').id, - copyLabel: t('core', 'Copy link'), - social: social, + var minPasswordLength = 4 + // password policy? + if(oc_capabilities.password_policy && oc_capabilities.password_policy.minLength) { + minPasswordLength = oc_capabilities.password_policy.minLength; + } - shareLinkURL: this.model.get('linkShare').link, + var popoverBase = { + social: social, urlLabel: t('core', 'Link'), - enablePasswordLabel: t('core', 'Password protect'), + hideDownloadLabel: t('core', 'Hide download'), + enablePasswordLabel: isPasswordEnforced ? t('core', 'Password protection enforced') : t('core', 'Password protect'), passwordLabel: t('core', 'Password'), - passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, passwordPlaceholderInitial: passwordPlaceholderInitial, - isPasswordSet: isPasswordSet || isPasswordEnabledByDefault || isPasswordEnforced, - showPasswordCheckBox: showPasswordCheckBox, - publicUpload: publicUpload && isLinkShare, + publicUpload: publicUpload, publicEditing: publicEditable, publicEditingChecked: publicEditingChecked, publicEditingLabel: t('core', 'Allow editing'), @@ -482,41 +614,43 @@ publicUploadRWValue: OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE, publicUploadRValue: OC.PERMISSION_READ, publicUploadWValue: OC.PERMISSION_CREATE, - publicUploadRWChecked: publicUploadRWChecked, - publicUploadRChecked: publicUploadRChecked, - publicUploadWChecked: publicUploadWChecked, - expireDateLabel: t('core', 'Set expiration date'), + expireDateLabel: isExpirationEnforced ? t('core', 'Expiration date enforced') : t('core', 'Set expiration date'), expirationLabel: t('core', 'Expiration'), expirationDatePlaceholder: t('core', 'Expiration date'), - hasExpireDate: hasExpireDate, isExpirationEnforced: isExpirationEnforced, isPasswordEnforced: isPasswordEnforced, - expireDate: expireDate, defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today - shareNote: this.model.get('linkShare').note, addNoteLabel: t('core', 'Note to recipient'), - }); + unshareLabel: t('core', 'Unshare'), + unshareLinkLabel: t('core', 'Delete share link'), + newShareLabel: t('core', 'Add another link'), + }; - var pendingPopover = this.pendingPopoverMenuTemplate({ - cid: this.model.get('linkShare').id, - enablePasswordLabel: t('core', 'Password protect'), - passwordLabel: t('core', 'Password'), - passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, - passwordPlaceholderInitial: passwordPlaceholderInitial, - showPasswordCheckBox: showPasswordCheckBox, + var pendingPopover = { isPasswordEnforced: isPasswordEnforced, - }); + enforcedPasswordLabel: t('core', 'Password protection for links is mandatory'), + passwordPlaceholder: passwordPlaceholderInitial, + minPasswordLength: minPasswordLength, + }; + var pendingPopoverMenu = this.pendingPopoverMenuTemplate(_.extend({}, pendingPopover)) + + var linkShares = this.getShareeList(); + if(_.isArray(linkShares)) { + for (var i = 0; i < linkShares.length; i++) { + var popover = this.getPopoverObject(linkShares[i]) + linkShares[i].popoverMenu = this.popoverMenuTemplate(_.extend({}, popoverBase, popover)); + linkShares[i].pendingPopoverMenu = pendingPopoverMenu + } + } this.$el.html(linkShareTemplate({ - cid: this.model.get('linkShare').id, + linkShares: linkShares, shareAllowed: true, - isLinkShare: isLinkShare, - linkShareLabel: t('core', 'Share link'), - linkShareEnableLabel: t('core', 'Enable'), - popoverMenu: popover, - pendingPopoverMenu: pendingPopover, - showMenu: isLinkShare || this.showPending, - showPending: this.showPending && !isLinkShare + nolinkShares: linkShares.length === 0, + newShareLabel: t('core', 'Share link'), + newShareTitle: t('core', 'New share link'), + pendingPopoverMenu: pendingPopoverMenu, + showPending: this.showPending === 'new', })); this.delegateEvents(); @@ -533,9 +667,17 @@ var $element = $(event.target); var $li = $element.closest('li[data-share-id]'); var $menu = $li.find('.sharingOptionsGroup .popovermenu'); + var shareId = $li.data('share-id'); OC.showMenu(null, $menu); - this._menuOpen = $li.data('share-id'); + + // focus the password if not set and enforced + var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; + var haspassword = $menu.find('.linkPassText').val() !== ''; + + if (!haspassword && isPasswordEnabledByDefault) { + $menu.find('.linkPassText').focus(); + } }, /** @@ -613,24 +755,179 @@ var $element = $(event.target); var li = $element.closest('li[data-share-id]'); var shareId = li.data('share-id'); + var maxDate = $element.data('max-date'); var expirationDatePicker = '#expirationDatePicker-' + shareId; var self = this; $(expirationDatePicker).datepicker({ dateFormat : 'dd-mm-yy', onSelect: function (expireDate) { - self.setExpirationDate(expireDate); - } + self.setExpirationDate(expireDate, shareId); + }, + maxDate: maxDate }); $(expirationDatePicker).datepicker('show'); $(expirationDatePicker).focus(); }, - setExpirationDate: function(expireDate) { - this.model.saveLinkShare({expireDate: expireDate}); + setExpirationDate: function(expireDate, shareId) { + this.model.saveLinkShare({expireDate: expireDate, cid: shareId}); }, + /** + * get an array of sharees' share properties + * + * @returns {Array} + */ + getShareeList: function() { + var shares = this.model.get('linkShares'); + + if(!this.model.hasLinkShares()) { + return []; + } + + var list = []; + for(var index = 0; index < shares.length; index++) { + var share = this.getShareeObject(index); + // first empty {} is necessary, otherwise we get in trouble + // with references + list.push(_.extend({}, share)); + } + + return list; + }, + + /** + * + * @param {OC.Share.Types.ShareInfo} shareInfo + * @returns {object} + */ + getShareeObject: function(shareIndex) { + var share = this.model.get('linkShares')[shareIndex]; + + return _.extend({}, share, { + cid: share.id, + shareAllowed: true, + linkShareLabel: share.label !== '' ? share.label : t('core', 'Share link'), + popoverMenu: {}, + shareLinkURL: share.url, + newShareTitle: t('core', 'New share link'), + copyLabel: t('core', 'Copy link'), + showPending: this.showPending === share.id, + }) + }, + + getPopoverObject: function(share) { + var publicUploadRWChecked = ''; + var publicUploadRChecked = ''; + var publicUploadWChecked = ''; + + switch (this.model.linkSharePermissions(share.id)) { + case OC.PERMISSION_READ: + publicUploadRChecked = 'checked'; + break; + case OC.PERMISSION_CREATE: + publicUploadWChecked = 'checked'; + break; + case OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE: + publicUploadRWChecked = 'checked'; + break; + } + + var isPasswordSet = !!share.password; + var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; + var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); + var showPasswordCheckBox = !isPasswordEnforced || !share.password; + var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); + var defaultExpireDays = this.configModel.get('defaultExpireDate'); + var hasExpireDate = !!share.expiration || isExpirationEnforced; + + var expireDate; + if (hasExpireDate) { + expireDate = moment(share.expiration, 'YYYY-MM-DD').format('DD-MM-YYYY'); + } + + var isTalkEnabled = oc_appswebroots['spreed'] !== undefined; + var sendPasswordByTalk = share.sendPasswordByTalk; + + var showHideDownloadCheckbox = !this.model.isFolder(); + var hideDownload = share.hideDownload; + + var maxDate = null; + + if(hasExpireDate) { + if(isExpirationEnforced) { + // TODO: hack: backend returns string instead of integer + var shareTime = share.stime; + if (_.isNumber(shareTime)) { + shareTime = new Date(shareTime * 1000); + } + if (!shareTime) { + shareTime = new Date(); // now + } + shareTime = OC.Util.stripTime(shareTime).getTime(); + maxDate = new Date(shareTime + defaultExpireDays * 24 * 3600 * 1000); + } + } + + return { + cid: share.id, + shareLinkURL: share.url, + passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, + isPasswordSet: isPasswordSet || isPasswordEnabledByDefault || isPasswordEnforced, + showPasswordCheckBox: showPasswordCheckBox, + showPasswordByTalkCheckBox: isTalkEnabled && isPasswordSet, + passwordByTalkLabel: t('core', 'Password protect by Talk'), + isPasswordByTalkSet: sendPasswordByTalk, + publicUploadRWChecked: publicUploadRWChecked, + publicUploadRChecked: publicUploadRChecked, + publicUploadWChecked: publicUploadWChecked, + hasExpireDate: hasExpireDate, + expireDate: expireDate, + shareNote: share.note, + hasNote: share.note !== '', + maxDate: maxDate, + showHideDownloadCheckbox: showHideDownloadCheckbox, + hideDownload: hideDownload, + isExpirationEnforced: isExpirationEnforced, + } + }, + + onUnshare: function(event) { + event.preventDefault(); + event.stopPropagation(); + var self = this; + var $element = $(event.target); + if (!$element.is('a')) { + $element = $element.closest('a'); + } + + var $loading = $element.find('.icon-loading-small').eq(0); + if(!$loading.hasClass('hidden')) { + // in process + return false; + } + $loading.removeClass('hidden'); + + var $li = $element.closest('li[data-share-id]'); + + var shareId = $li.data('share-id'); + + self.model.removeShare(shareId, { + success: function() { + $li.remove(); + self.render() + }, + error: function() { + $loading.addClass('hidden'); + OC.Notification.showTemporary(t('core', 'Could not unshare')); + } + }); + return false; + }, + + }); OC.Share.ShareDialogLinkShareView = ShareDialogLinkShareView; diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index 93373a54435..8b709f0d74d 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -134,6 +134,8 @@ var hasPassword = password !== null && password !== ''; var sendPasswordByTalk = share.send_password_by_talk; + var shareNote = this.model.getNote(shareIndex); + return _.extend(hasPermissionOverride, { cid: this.cid, hasSharePermission: this.model.hasSharePermission(shareIndex), @@ -159,7 +161,8 @@ isTalkEnabled: oc_appswebroots['spreed'] !== undefined, secureDropMode: !this.model.hasReadPermission(shareIndex), hasExpireDate: this.model.getExpireDate(shareIndex) !== null, - shareNote: this.model.getNote(shareIndex), + shareNote: shareNote, + hasNote: shareNote !== '', expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'), // The password placeholder does not take into account if // sending the password by Talk is enabled or not; when @@ -314,7 +317,9 @@ var $edit = _this.$('#canEdit-' + _this.cid + '-' + sharee.shareId); if($edit.length === 1) { $edit.prop('checked', sharee.editPermissionState === 'checked'); - $edit.prop('indeterminate', sharee.editPermissionState === 'indeterminate'); + if (sharee.isFolder) { + $edit.prop('indeterminate', sharee.editPermissionState === 'indeterminate'); + } } }); this.$('.popovermenu').on('afterHide', function() { @@ -384,7 +389,7 @@ var $form = $menu.next('li.share-note-form'); // show elements - $menu.find('.share-note-delete').toggle(); + $menu.find('.share-note-delete').toggleClass('hidden'); $form.toggleClass('hidden'); $form.find('textarea').focus(); }, @@ -403,7 +408,7 @@ $form.find('.share-note').val(''); $form.addClass('hidden'); - $menu.find('.share-note-delete').hide(); + $menu.find('.share-note-delete').addClass('hidden'); self.sendNote('', shareId, $menu); }, diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index 9c648357e61..082bf9571d7 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -312,6 +312,41 @@ var suggestions = exactMatches.concat(users).concat(groups).concat(remotes).concat(remoteGroups).concat(emails).concat(circles).concat(rooms).concat(lookup); + function dynamicSort(property) { + return function (a,b) { + var aProperty = ''; + var bProperty = ''; + if (typeof a[property] !== 'undefined') { + aProperty = a[property]; + } + if (typeof b[property] !== 'undefined') { + bProperty = b[property]; + } + return (aProperty < bProperty) ? -1 : (aProperty > bProperty) ? 1 : 0; + } + } + + /** + * Sort share entries by uuid to properly group them + */ + var grouped = suggestions.sort(dynamicSort('uuid')); + + var previousUuid = null; + var groupedLength = grouped.length; + var result = []; + /** + * build the result array that only contains all contact entries from + * merged contacts, if the search term matches its contact name + */ + for (i = 0; i < groupedLength; i++) { + if (typeof grouped[i].uuid !== 'undefined' && grouped[i].uuid === previousUuid) { + grouped[i].merged = true; + } + if (searchTerm === grouped[i].name || typeof grouped[i].merged === 'undefined') { + result.push(grouped[i]); + } + previousUuid = grouped[i].uuid; + } var moreResultsAvailable = ( oc_config['sharing.maxAutocompleteResults'] > 0 @@ -328,7 +363,7 @@ ) ); - deferred.resolve(suggestions, exactMatches, moreResultsAvailable); + deferred.resolve(result, exactMatches, moreResultsAvailable); } else { deferred.reject(result.ocs.meta.message); } @@ -441,33 +476,72 @@ }, autocompleteRenderItem: function(ul, item) { - + var icon = 'icon-user'; var text = item.label; + if (typeof item.name !== 'undefined') { + text = item.name; + } if (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) { - text = t('core', '{sharee} (group)', { sharee: text }, undefined, { escape: false }); + icon = 'icon-contacts-dark'; } else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE) { - text = t('core', '{sharee} (remote)', {sharee: text}, undefined, {escape: false}); + icon = 'icon-shared'; } else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) { text = t('core', '{sharee} (remote group)', { sharee: text }, undefined, { escape: false }); + icon = 'icon-shared'; } else if (item.value.shareType === OC.Share.SHARE_TYPE_EMAIL) { - text = t('core', '{sharee} (email)', { sharee: text }, undefined, { escape: false }); + icon = 'icon-mail'; } else if (item.value.shareType === OC.Share.SHARE_TYPE_CIRCLE) { text = t('core', '{sharee} ({type}, {owner})', {sharee: text, type: item.value.circleInfo, owner: item.value.circleOwner}, undefined, {escape: false}); + icon = 'icon-circle'; } else if (item.value.shareType === OC.Share.SHARE_TYPE_ROOM) { - text = t('core', '{sharee} (conversation)', { sharee: text }, undefined, { escape: false }); + icon = 'icon-talk'; + } + var description = ''; + var getTranslatedType = function(type) { + switch (type) { + case 'HOME': + return t('core', 'Home'); + case 'WORK': + return t('core', 'Home'); + case 'OTHER': + return t('core', 'Other'); + default: + return type; + } + }; + if (typeof item.type !== 'undefined' && item.type !== null) { + description = getTranslatedType(item.type); } var insert = $("<div class='share-autocomplete-item'/>"); - var avatar = $("<div class='avatardiv'></div>").appendTo(insert); - if (item.value.shareType === OC.Share.SHARE_TYPE_USER || item.value.shareType === OC.Share.SHARE_TYPE_CIRCLE) { - avatar.avatar(item.value.shareWith, 32, undefined, undefined, undefined, item.label); + if (item.merged) { + insert.addClass('merged'); + text = item.value.shareWith; } else { - avatar.imageplaceholder(text, undefined, 32); + var avatar = $("<div class='avatardiv'></div>").appendTo(insert); + if (item.value.shareType === OC.Share.SHARE_TYPE_USER || item.value.shareType === OC.Share.SHARE_TYPE_CIRCLE) { + avatar.avatar(item.value.shareWith, 32, undefined, undefined, undefined, item.label); + } else { + if (typeof item.uuid === 'undefined') { + item.uuid = text; + } + avatar.imageplaceholder(item.uuid, text, 32); + } + description = item.value.shareWith; + } + if (description !== '') { + insert.addClass('with-description'); } $("<div class='autocomplete-item-text'></div>") - .text(text) + .html( + text.replace( + new RegExp(this.term, "gi"), + "<span class='ui-state-highlight'>$&</span>") + + '<span class="autocomplete-item-details">' + description + '</span>' + ) .appendTo(insert); insert.attr('title', item.value.shareWith); + insert.append('<span class="icon '+icon+'" title="' + text + '"></span>'); insert = $("<a>") .append(insert); return $("<li>") @@ -479,6 +553,20 @@ _onSelectRecipient: function(e, s) { var self = this; + if (e.keyCode == 9) { + e.preventDefault(); + if (typeof s.item.name !== 'undefined') { + e.target.value = s.item.name; + } else { + e.target.value = s.item.label; + } + setTimeout(function() { + $(e.target).attr('disabled', false) + .autocomplete('search', $(e.target).val()); + }, 0); + return false; + } + e.preventDefault(); // Ensure that the keydown handler for the input field is not // called; otherwise it would try to add the recipient again, which diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index f4a3caf1370..f4ac03e1c18 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -16,10 +16,10 @@ /** * @typedef {object} OC.Share.Types.LinkShareInfo - * @property {bool} isLinkShare * @property {string} token + * @property {bool} hideDownload * @property {string|null} password - * @property {string} link + * @property {bool} sendPasswordByTalk * @property {number} permissions * @property {Date} expiration * @property {number} stime share time @@ -99,7 +99,7 @@ defaults: { allowPublicUploadStatus: false, permissions: 0, - linkShare: {} + linkShares: [] }, /** @@ -129,15 +129,20 @@ delete attributes.expiration; } - if (this.get('linkShare') && this.get('linkShare').isLinkShare) { - shareId = this.get('linkShare').id; + var linkShares = this.get('linkShares'); + var shareIndex = _.findIndex(linkShares, function(share) {return share.id === attributes.cid}) + + if (linkShares.length > 0 && shareIndex !== -1) { + shareId = linkShares[shareIndex].id; // note: update can only update a single value at a time call = this.updateShare(shareId, attributes, options); } else { attributes = _.defaults(attributes, { + hideDownload: false, password: '', passwordChanged: false, + sendPasswordByTalk: false, permissions: OC.PERMISSION_READ, expireDate: this.configModel.getDefaultExpirationDateString(), shareType: OC.Share.SHARE_TYPE_LINK @@ -149,12 +154,6 @@ return call; }, - removeLinkShare: function() { - if (this.get('linkShare')) { - return this.removeShare(this.get('linkShare').id); - } - }, - addShare: function(attributes, options) { var shareType = attributes.shareType; attributes = _.extend({}, attributes); @@ -314,13 +313,13 @@ }, /** - * Returns whether this item has a link share + * Returns whether this item has link shares * * @return {bool} true if a link share exists, false otherwise */ - hasLinkShare: function() { - var linkShare = this.get('linkShare'); - if (linkShare && linkShare.isLinkShare) { + hasLinkShares: function() { + var linkShares = this.get('linkShares'); + if (linkShares && linkShares.length > 0) { return true; } return false; @@ -614,6 +613,12 @@ var hcp = this.hasCreatePermission(shareIndex); var hup = this.hasUpdatePermission(shareIndex); var hdp = this.hasDeletePermission(shareIndex); + if (this.isFile()) { + if (hcp || hup || hdp) { + return 'checked'; + } + return ''; + } if (!hcp && !hup && !hdp) { return ''; } @@ -628,12 +633,16 @@ /** * @returns {int} */ - linkSharePermissions: function() { - if (!this.hasLinkShare()) { + linkSharePermissions: function(shareId) { + var linkShares = this.get('linkShares'); + var shareIndex = _.findIndex(linkShares, function(share) {return share.id === shareId}) + + if (!this.hasLinkShares()) { return -1; - } else { - return this.get('linkShare').permissions; + } else if (linkShares.length > 0 && shareIndex !== -1) { + return linkShares[shareIndex].permissions; } + return -1; }, _getUrl: function(base, params) { @@ -829,7 +838,7 @@ this._legacyFillCurrentShares(shares); - var linkShare = { isLinkShare: false }; + var linkShares = []; // filter out the share by link shares = _.reject(shares, /** @@ -842,7 +851,7 @@ || share.item_source === this.get('itemSource')); if (isShareLink) { - /* + /** * Ignore reshared link shares for now * FIXME: Find a way to display properly */ @@ -862,17 +871,13 @@ } else { link += OC.generateUrl('/s/') + share.token; } - linkShare = { - isLinkShare: true, - id: share.id, - token: share.token, + linkShares.push(_.extend({}, share, { + // hide_download is returned as an int, so force it + // to a boolean + hideDownload: !!share.hide_download, password: share.share_with, - link: link, - permissions: share.permissions, - // currently expiration is only effective for link shares. - expiration: share.expiration, - stime: share.stime - }; + sendPasswordByTalk: share.send_password_by_talk + })); return share; } @@ -883,7 +888,7 @@ return { reshare: data.reshare, shares: shares, - linkShare: linkShare, + linkShares: linkShares, permissions: permissions, allowPublicUploadStatus: allowPublicUploadStatus, allowPublicEditingStatus: allowPublicEditingStatus, @@ -919,7 +924,7 @@ getShareTypes: function() { var result; result = _.pluck(this.getSharesWithCurrentItem(), 'share_type'); - if (this.hasLinkShare()) { + if (this.hasLinkShares()) { result.push(OC.Share.SHARE_TYPE_LINK); } return _.uniq(result); diff --git a/core/js/sharetemplates.js b/core/js/sharetemplates.js index efdd3ff6606..6469e264d75 100644 --- a/core/js/sharetemplates.js +++ b/core/js/sharetemplates.js @@ -1,33 +1,28 @@ (function() { var template = Handlebars.template, templates = OC.Share.Templates = OC.Share.Templates || {}; templates['sharedialoglinkshareview'] = template({"1":function(container,depth0,helpers,partials,data) { - var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {}); - return "<ul id=\"shareLink\" class=\"shareWithList\">\n <li data-share-id=\"" - + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\">\n <div class=\"avatar icon-public-white\"></div><span class=\"username\" title=\"" - + alias4(((helper = (helper = helpers.linkShareLabel || (depth0 != null ? depth0.linkShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareLabel","hash":{},"data":data}) : helper))) - + "\">" - + alias4(((helper = (helper = helpers.linkShareLabel || (depth0 != null ? depth0.linkShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareLabel","hash":{},"data":data}) : helper))) - + "</span>\n <span class=\"sharingOptionsGroup\">\n <span class=\"shareOption\">\n <span class=\"icon-loading-small hidden\"></span>\n <input id=\"linkCheckbox-" - + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\" " - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isLinkShare : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " type=\"checkbox\" name=\"linkCheckbox\" class=\"linkCheckbox permissions checkbox\">\n <label for=\"linkCheckbox-" - + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\">" - + alias4(((helper = (helper = helpers.linkShareEnableLabel || (depth0 != null ? depth0.linkShareEnableLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareEnableLabel","hash":{},"data":data}) : helper))) - + "</label>\n </span>\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showMenu : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " </span>\n </li>\n</ul>\n"; + return "<ul class=\"shareWithList\">\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.nolinkShares : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.linkShares : depth0),{"name":"each","hash":{},"fn":container.program(7, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "</ul>\n"; },"2":function(container,depth0,helpers,partials,data) { - return "checked=\"checked\""; -},"4":function(container,depth0,helpers,partials,data) { - var stack1; + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <div class=\"share-menu\" tabindex=\"0\"><span class=\"icon icon-more\"></span>\n" - + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(7, data, 0),"data":data})) != null ? stack1 : "") - + " </div>\n"; + return " <li data-share-id=\"new-share\">\n <div class=\"avatar icon-public-white\"></div>\n <span class=\"username\">" + + alias4(((helper = (helper = helpers.newShareLabel || (depth0 != null ? depth0.newShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newShareLabel","hash":{},"data":data}) : helper))) + + "</span>\n <span class=\"sharingOptionsGroup\">\n <div class=\"share-menu\">\n <a href=\"#\" class=\"icon icon-add new-share has-tooltip " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\" title=\"" + + alias4(((helper = (helper = helpers.newShareTitle || (depth0 != null ? depth0.newShareTitle : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newShareTitle","hash":{},"data":data}) : helper))) + + "\"></a>\n <span class=\"icon icon-loading-small " + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"unless","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\"></span>\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " </div>\n </span>\n </li>\n"; +},"3":function(container,depth0,helpers,partials,data) { + return "hidden"; },"5":function(container,depth0,helpers,partials,data) { var stack1, helper; @@ -35,33 +30,53 @@ templates['sharedialoglinkshareview'] = template({"1":function(container,depth0, + ((stack1 = ((helper = (helper = helpers.pendingPopoverMenu || (depth0 != null ? depth0.pendingPopoverMenu : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"pendingPopoverMenu","hash":{},"data":data}) : helper))) != null ? stack1 : "") + "\n"; },"7":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <li data-share-id=\"" + + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + + "\">\n <div class=\"avatar icon-public-white\"></div><span class=\"username\" title=\"" + + alias4(((helper = (helper = helpers.linkShareLabel || (depth0 != null ? depth0.linkShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareLabel","hash":{},"data":data}) : helper))) + + "\">" + + alias4(((helper = (helper = helpers.linkShareLabel || (depth0 != null ? depth0.linkShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareLabel","hash":{},"data":data}) : helper))) + + "</span>\n \n <span class=\"sharingOptionsGroup\">\n <a href=\"#\" class=\"clipboard-button icon icon-clippy has-tooltip\" data-clipboard-text=\"" + + alias4(((helper = (helper = helpers.shareLinkURL || (depth0 != null ? depth0.shareLinkURL : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareLinkURL","hash":{},"data":data}) : helper))) + + "\" title=\"" + + alias4(((helper = (helper = helpers.copyLabel || (depth0 != null ? depth0.copyLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"copyLabel","hash":{},"data":data}) : helper))) + + "\"></a>\n <div class=\"share-menu\">\n <a href=\"#\" class=\"icon icon-more " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\"></a>\n <span class=\"icon icon-loading-small " + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"unless","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\"></span>\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(8, data, 0),"data":data})) != null ? stack1 : "") + + " </div>\n </span>\n </li>\n"; +},"8":function(container,depth0,helpers,partials,data) { var stack1, helper; return " " + ((stack1 = ((helper = (helper = helpers.popoverMenu || (depth0 != null ? depth0.popoverMenu : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"popoverMenu","hash":{},"data":data}) : helper))) != null ? stack1 : "") + "\n"; -},"9":function(container,depth0,helpers,partials,data) { +},"10":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.noSharingPlaceholder : depth0),{"name":"if","hash":{},"fn":container.program(10, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.noSharingPlaceholder : depth0),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n"; -},"10":function(container,depth0,helpers,partials,data) { +},"11":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; return "<input id=\"shareWith-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\" class=\"shareWithField\" type=\"text\" placeholder=\"" + alias4(((helper = (helper = helpers.noSharingPlaceholder || (depth0 != null ? depth0.noSharingPlaceholder : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"noSharingPlaceholder","hash":{},"data":data}) : helper))) - + "\" disabled=\"disabled\"/>"; + + "\" disabled=\"disabled\" />"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.shareAllowed : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(9, data, 0),"data":data})) != null ? stack1 : ""); + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.shareAllowed : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(10, data, 0),"data":data})) != null ? stack1 : ""); },"useData":true}); templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li>\n <span class=\"shareOption menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"radio\" name=\"publicUpload\" value=\"" + return " <li>\n <span class=\"menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"radio\" name=\"publicUpload\" value=\"" + alias4(((helper = (helper = helpers.publicUploadRValue || (depth0 != null ? depth0.publicUploadRValue : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"publicUploadRValue","hash":{},"data":data}) : helper))) + "\" id=\"sharingDialogAllowPublicUpload-r-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) @@ -71,7 +86,7 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\">" + alias4(((helper = (helper = helpers.publicUploadRLabel || (depth0 != null ? depth0.publicUploadRLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"publicUploadRLabel","hash":{},"data":data}) : helper))) - + "</label>\n </span>\n </li>\n <li>\n <span class=\"shareOption menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"radio\" name=\"publicUpload\" value=\"" + + "</label>\n </span>\n </li>\n <li>\n <span class=\"menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"radio\" name=\"publicUpload\" value=\"" + alias4(((helper = (helper = helpers.publicUploadRWValue || (depth0 != null ? depth0.publicUploadRWValue : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"publicUploadRWValue","hash":{},"data":data}) : helper))) + "\" id=\"sharingDialogAllowPublicUpload-rw-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) @@ -81,7 +96,7 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\">" + alias4(((helper = (helper = helpers.publicUploadRWLabel || (depth0 != null ? depth0.publicUploadRWLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"publicUploadRWLabel","hash":{},"data":data}) : helper))) - + "</label>\n </span></li>\n <li>\n <span class=\"shareOption menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"radio\" name=\"publicUpload\" value=\"" + + "</label>\n </span>\n </li>\n <li>\n <span class=\"menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"radio\" name=\"publicUpload\" value=\"" + alias4(((helper = (helper = helpers.publicUploadWValue || (depth0 != null ? depth0.publicUploadWValue : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"publicUploadWValue","hash":{},"data":data}) : helper))) + "\" id=\"sharingDialogAllowPublicUpload-w-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) @@ -95,7 +110,7 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont },"3":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li id=\"allowPublicEditingWrapper\">\n <span class=\"shareOption menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"checkbox\" name=\"allowPublicEditing\" id=\"sharingDialogAllowPublicEditing-" + return " <li id=\"allowPublicEditingWrapper\">\n <span class=\"menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"checkbox\" name=\"allowPublicEditing\" id=\"sharingDialogAllowPublicEditing-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\" class=\"checkbox publicEditingCheckbox\" " + ((stack1 = ((helper = (helper = helpers.publicEditingChecked || (depth0 != null ? depth0.publicEditingChecked : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"publicEditingChecked","hash":{},"data":data}) : helper))) != null ? stack1 : "") @@ -107,41 +122,69 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont },"5":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li>\n <span class=\"shareOption menuitem\">\n <input type=\"checkbox\" name=\"showPassword\" id=\"showPassword-" + return " <li>\n <span class=\"menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"checkbox\" name=\"hideDownload\" id=\"sharingDialogHideDownload-" + + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + + "\" class=\"checkbox hideDownloadCheckbox\"\n " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hideDownload : depth0),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " />\n <label for=\"sharingDialogHideDownload-" + + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + + "\">" + + alias4(((helper = (helper = helpers.hideDownloadLabel || (depth0 != null ? depth0.hideDownloadLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"hideDownloadLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n"; +},"6":function(container,depth0,helpers,partials,data) { + return "checked=\"checked\""; +},"8":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <li>\n <span class=\"menuitem\">\n <input type=\"checkbox\" name=\"showPassword\" id=\"showPassword-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\" class=\"checkbox showPasswordCheckbox\"\n " + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isPasswordSet : depth0),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " " - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isPasswordEnforced : depth0),{"name":"if","hash":{},"fn":container.program(8, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isPasswordEnforced : depth0),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " value=\"1\" />\n <label for=\"showPassword-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\">" + alias4(((helper = (helper = helpers.enablePasswordLabel || (depth0 != null ? depth0.enablePasswordLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"enablePasswordLabel","hash":{},"data":data}) : helper))) + "</label>\n </span>\n </li>\n <li class=\"" - + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.isPasswordSet : depth0),{"name":"unless","hash":{},"fn":container.program(10, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " linkPassMenu\">\n <span class=\"shareOption menuitem icon-share-pass\">\n <input id=\"linkPassText-" + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.isPasswordSet : depth0),{"name":"unless","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " linkPassMenu\">\n <span class=\"menuitem icon-share-pass\">\n <input id=\"linkPassText-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\" class=\"linkPassText\" type=\"password\" placeholder=\"" + alias4(((helper = (helper = helpers.passwordPlaceholder || (depth0 != null ? depth0.passwordPlaceholder : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"passwordPlaceholder","hash":{},"data":data}) : helper))) + "\" autocomplete=\"new-password\" />\n <span class=\"icon icon-loading-small hidden\"></span>\n </span>\n </li>\n"; -},"6":function(container,depth0,helpers,partials,data) { - return "checked=\"checked\""; -},"8":function(container,depth0,helpers,partials,data) { +},"9":function(container,depth0,helpers,partials,data) { return "disabled=\"disabled\""; -},"10":function(container,depth0,helpers,partials,data) { +},"11":function(container,depth0,helpers,partials,data) { return "hidden"; -},"12":function(container,depth0,helpers,partials,data) { +},"13":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <li>\n <span class=\"shareOption menuitem\">\n <span class=\"icon-loading-small hidden\"></span>\n <input type=\"checkbox\" name=\"passwordByTalk\" id=\"passwordByTalk-" + + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + + "\" class=\"checkbox passwordByTalkCheckbox\"\n " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isPasswordByTalkSet : depth0),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " />\n <label for=\"passwordByTalk-" + + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + + "\">" + + alias4(((helper = (helper = helpers.passwordByTalkLabel || (depth0 != null ? depth0.passwordByTalkLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"passwordByTalkLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n"; +},"15":function(container,depth0,helpers,partials,data) { + return "datepicker"; +},"17":function(container,depth0,helpers,partials,data) { var helper; return container.escapeExpression(((helper = (helper = helpers.expireDate || (depth0 != null ? depth0.expireDate : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"expireDate","hash":{},"data":data}) : helper))); -},"14":function(container,depth0,helpers,partials,data) { +},"19":function(container,depth0,helpers,partials,data) { var helper; return container.escapeExpression(((helper = (helper = helpers.defaultExpireDate || (depth0 != null ? depth0.defaultExpireDate : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"defaultExpireDate","hash":{},"data":data}) : helper))); -},"16":function(container,depth0,helpers,partials,data) { +},"21":function(container,depth0,helpers,partials,data) { + return "readonly"; +},"23":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li>\n <a href=\"#\" class=\"shareOption menuitem pop-up\" data-url=\"" + return " <li>\n <a href=\"#\" class=\"menuitem pop-up\" data-url=\"" + alias4(((helper = (helper = helpers.url || (depth0 != null ? depth0.url : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"url","hash":{},"data":data}) : helper))) + "\" data-window=\"" + alias4(((helper = (helper = helpers.newWindow || (depth0 != null ? depth0.newWindow : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newWindow","hash":{},"data":data}) : helper))) @@ -153,30 +196,28 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "<div class=\"popovermenu menu\">\n <ul>\n <li>\n <a href=\"#\" class=\"menuitem clipboardButton\" data-clipboard-text=\"" - + alias4(((helper = (helper = helpers.shareLinkURL || (depth0 != null ? depth0.shareLinkURL : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareLinkURL","hash":{},"data":data}) : helper))) - + "\">\n <span class=\"icon icon-clippy\" ></span>\n <span>" - + alias4(((helper = (helper = helpers.copyLabel || (depth0 != null ? depth0.copyLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"copyLabel","hash":{},"data":data}) : helper))) - + "</span>\n </a>\n </li>\n <li class=\"hidden linkTextMenu\">\n <span class=\"menuitem icon-link-text\">\n <input id=\"linkText-" + return "<div class=\"popovermenu menu\">\n <ul>\n <li class=\"hidden linkTextMenu\">\n <span class=\"menuitem icon-link-text\">\n <input id=\"linkText-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\" class=\"linkText\" type=\"text\" readonly=\"readonly\" value=\"" + alias4(((helper = (helper = helpers.shareLinkURL || (depth0 != null ? depth0.shareLinkURL : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareLinkURL","hash":{},"data":data}) : helper))) + "\" />\n </span>\n </li>\n" + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.publicUpload : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.publicEditing : depth0),{"name":"if","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPasswordCheckBox : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " <li>\n <span class=\"shareOption menuitem\">\n <input id=\"expireDate-" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showHideDownloadCheckbox : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPasswordCheckBox : depth0),{"name":"if","hash":{},"fn":container.program(8, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPasswordByTalkCheckBox : depth0),{"name":"if","hash":{},"fn":container.program(13, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " <li>\n <span class=\"menuitem\">\n <input id=\"expireDate-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\" type=\"checkbox\" name=\"expirationDate\" class=\"expireDate checkbox\"\n " + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " " - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isExpirationEnforced : depth0),{"name":"if","hash":{},"fn":container.program(8, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "\" />\n <label for=\"expireDate-" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isExpirationEnforced : depth0),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " />\n <label for=\"expireDate-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\">" + alias4(((helper = (helper = helpers.expireDateLabel || (depth0 != null ? depth0.expireDateLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"expireDateLabel","hash":{},"data":data}) : helper))) + "</label>\n </span>\n </li>\n <li class=\"" - + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"unless","hash":{},"fn":container.program(10, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"unless","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\">\n <span class=\"menuitem icon-expiredate expirationDateContainer-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "\">\n <label for=\"expirationDatePicker-" @@ -185,40 +226,50 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont + alias4(((helper = (helper = helpers.expirationDate || (depth0 != null ? depth0.expirationDate : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"expirationDate","hash":{},"data":data}) : helper))) + "\">" + alias4(((helper = (helper = helpers.expirationLabel || (depth0 != null ? depth0.expirationLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"expirationLabel","hash":{},"data":data}) : helper))) - + "</label>\n <input id=\"expirationDatePicker-" + + "</label>\n <!-- do not use the datepicker if enforced -->\n <input id=\"expirationDatePicker-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\" class=\"datepicker\" type=\"text\" placeholder=\"" + + "\" class=\"" + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.isExpirationEnforced : depth0),{"name":"unless","hash":{},"fn":container.program(15, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\" type=\"text\"\n placeholder=\"" + alias4(((helper = (helper = helpers.expirationDatePlaceholder || (depth0 != null ? depth0.expirationDatePlaceholder : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"expirationDatePlaceholder","hash":{},"data":data}) : helper))) + "\" value=\"" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"if","hash":{},"fn":container.program(12, data, 0),"inverse":container.program(14, data, 0),"data":data})) != null ? stack1 : "") - + "\" />\n </span>\n </li>\n <li>\n <a href=\"#\" class=\"share-add\">\n <span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-edit\"></span>\n <span>" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0),"inverse":container.program(19, data, 0),"data":data})) != null ? stack1 : "") + + "\"\n data-max-date=\"" + + alias4(((helper = (helper = helpers.maxDate || (depth0 != null ? depth0.maxDate : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"maxDate","hash":{},"data":data}) : helper))) + + "\" " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isExpirationEnforced : depth0),{"name":"if","hash":{},"fn":container.program(21, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " />\n </span>\n </li>\n <li>\n <a href=\"#\" class=\"share-add\">\n <span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-edit\"></span>\n <span>" + alias4(((helper = (helper = helpers.addNoteLabel || (depth0 != null ? depth0.addNoteLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"addNoteLabel","hash":{},"data":data}) : helper))) - + "</span>\n <input type=\"button\" class=\"share-note-delete icon-delete\">\n </a>\n </li>\n <li class=\"share-note-form share-note-link hidden\">\n <span class=\"menuitem icon-note\">\n <textarea class=\"share-note\">" + + "</span>\n <input type=\"button\" class=\"share-note-delete icon-delete " + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasNote : depth0),{"name":"unless","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\">\n </a>\n </li>\n <li class=\"share-note-form share-note-link " + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasNote : depth0),{"name":"unless","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\">\n <span class=\"menuitem icon-note\">\n <textarea class=\"share-note\">" + alias4(((helper = (helper = helpers.shareNote || (depth0 != null ? depth0.shareNote : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareNote","hash":{},"data":data}) : helper))) + "</textarea>\n <input type=\"submit\" class=\"icon-confirm share-note-submit\" value=\"\" id=\"add-note-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) - + "\" />\n </span>\n </li>\n" - + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.social : depth0),{"name":"each","hash":{},"fn":container.program(16, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " </ul>\n</div>\n"; + + "\" />\n </span>\n </li>\n" + + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.social : depth0),{"name":"each","hash":{},"fn":container.program(23, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " <li>\n <a href=\"#\" class=\"unshare\"><span class=\"icon-loading-small hidden\"></span><span class=\"icon icon-delete\"></span><span>" + + alias4(((helper = (helper = helpers.unshareLinkLabel || (depth0 != null ? depth0.unshareLinkLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"unshareLinkLabel","hash":{},"data":data}) : helper))) + + "</span></a>\n </li>\n <li>\n <a href=\"#\" class=\"new-share\">\n <span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-add\"></span>\n <span>" + + alias4(((helper = (helper = helpers.newShareLabel || (depth0 != null ? depth0.newShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newShareLabel","hash":{},"data":data}) : helper))) + + "</span>\n </a>\n </li>\n </ul>\n</div>\n"; },"useData":true}); templates['sharedialoglinkshareview_popover_menu_pending'] = template({"1":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li><span class=\"shareOption menuitem\">\n <input type=\"checkbox\" name=\"showPassword\" id=\"showPassword-" - + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\" checked=\"checked\" disabled class=\"checkbox showPasswordCheckbox\" value=\"1\" />\n <label for=\"showPassword-" - + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\">" - + alias4(((helper = (helper = helpers.enablePasswordLabel || (depth0 != null ? depth0.enablePasswordLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"enablePasswordLabel","hash":{},"data":data}) : helper))) - + "</label>\n </span></li>\n <li class=\"linkPassMenu\"><span class=\"shareOption menuitem icon-share-pass\">\n <input id=\"linkPassText-" - + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) - + "\" class=\"linkPassText\" type=\"password\" placeholder=\"" + return " <li>\n <span class=\"menuitem icon-info\">\n <p>" + + alias4(((helper = (helper = helpers.enforcedPasswordLabel || (depth0 != null ? depth0.enforcedPasswordLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"enforcedPasswordLabel","hash":{},"data":data}) : helper))) + + "</p>\n </span>\n </li>\n <li class=\"linkPassMenu\">\n <span class=\"menuitem\">\n <form autocomplete=\"off\" class=\"enforcedPassForm\">\n <input id=\"enforcedPassText\" required class=\"enforcedPassText\" type=\"password\"\n placeholder=\"" + alias4(((helper = (helper = helpers.passwordPlaceholder || (depth0 != null ? depth0.passwordPlaceholder : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"passwordPlaceholder","hash":{},"data":data}) : helper))) - + "\" autocomplete=\"new-password\" />\n <span class=\"icon icon-loading-small hidden\"></span>\n </span></li>\n"; + + "\" autocomplete=\"enforcedPassText\" minlength=\"" + + alias4(((helper = (helper = helpers.minPasswordLength || (depth0 != null ? depth0.minPasswordLength : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"minPasswordLength","hash":{},"data":data}) : helper))) + + "\" />\n <input type=\"submit\" value=\" \" class=\"primary icon-checkmark-white\">\n </form>\n </span>\n </li>\n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var stack1; - return "<div class=\"popovermenu pendingpopover menu\">\n <ul>\n" + return "<div class=\"popovermenu open menu\">\n <ul>\n" + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.isPasswordEnforced : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " </ul>\n</div>\n"; },"useData":true}); @@ -280,7 +331,7 @@ templates['sharedialogshareelistview'] = template({"1":function(container,depth0 },"6":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <span class=\"shareOption\">\n <input id=\"canEdit-" + return " <span>\n <input id=\"canEdit-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -330,7 +381,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con },"3":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "\n <li>\n <span class=\"shareOption menuitem\">\n <input id=\"canShare-" + return "\n <li>\n <span class=\"menuitem\">\n <input id=\"canShare-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -364,7 +415,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con },"8":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "\n <li>\n <span class=\"shareOption menuitem\">\n <input id=\"canCreate-" + return "\n <li>\n <span class=\"menuitem\">\n <input id=\"canCreate-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -386,7 +437,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con },"11":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "\n <li>\n <span class=\"shareOption menuitem\">\n <input id=\"canUpdate-" + return "\n <li>\n <span class=\"menuitem\">\n <input id=\"canUpdate-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -408,7 +459,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con },"14":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "\n <li>\n <span class=\"shareOption menuitem\">\n <input id=\"canDelete-" + return "\n <li>\n <span class=\"menuitem\">\n <input id=\"canDelete-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -427,7 +478,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; return ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasCreatePermission : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " <li>\n <span class=\"shareOption menuitem\">\n <input id=\"password-" + + " <li>\n <span class=\"menuitem\">\n <input id=\"password-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -471,7 +522,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con },"17":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li>\n <span class=\"shareOption menuitem\">\n <input id=\"secureDrop-" + return " <li>\n <span class=\"menuitem\">\n <input id=\"secureDrop-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -497,7 +548,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con },"24":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li>\n <span class=\"shareOption menuitem\">\n <input id=\"passwordByTalk-" + return " <li>\n <span class=\"menuitem\">\n <input id=\"passwordByTalk-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -545,11 +596,15 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con return container.escapeExpression(((helper = (helper = helpers.defaultExpireDate || (depth0 != null ? depth0.defaultExpireDate : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"defaultExpireDate","hash":{},"data":data}) : helper))); },"30":function(container,depth0,helpers,partials,data) { - var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return " <li>\n <a href=\"#\" class=\"share-add\"><span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-edit\"></span>\n <span>" + return " <li>\n <a href=\"#\" class=\"share-add\">\n <span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-edit\"></span>\n <span>" + alias4(((helper = (helper = helpers.addNoteLabel || (depth0 != null ? depth0.addNoteLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"addNoteLabel","hash":{},"data":data}) : helper))) - + "</span>\n <input type=\"button\" class=\"share-note-delete icon-delete\">\n </a>\n </li>\n <li class=\"share-note-form hidden\">\n <span class=\"menuitem icon-note\">\n <textarea class=\"share-note\">" + + "</span>\n <input type=\"button\" class=\"share-note-delete icon-delete " + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasNote : depth0),{"name":"unless","hash":{},"fn":container.program(22, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\">\n </a>\n </li>\n <li class=\"share-note-form " + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasNote : depth0),{"name":"unless","hash":{},"fn":container.program(22, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\">\n <span class=\"menuitem icon-note\">\n <textarea class=\"share-note\">" + alias4(((helper = (helper = helpers.shareNote || (depth0 != null ? depth0.shareNote : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareNote","hash":{},"data":data}) : helper))) + "</textarea>\n <input type=\"submit\" class=\"icon-confirm share-note-submit\" value=\"\" id=\"add-note-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) @@ -562,7 +617,7 @@ templates['sharedialogshareelistview_popover_menu'] = template({"1":function(con + "\n" + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isFolder : depth0),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isMailShare : depth0),{"name":"if","hash":{},"fn":container.program(16, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " <li>\n <span class=\"shareOption menuitem\">\n <input id=\"expireDate-" + + " <li>\n <span class=\"menuitem\">\n <input id=\"expireDate-" + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper))) + "-" + alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper))) diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js index f2fc2888448..45a0f04db00 100644 --- a/core/js/tests/specHelper.js +++ b/core/js/tests/specHelper.js @@ -103,6 +103,8 @@ window.oc_appconfig = { window.oc_defaults = { docPlaceholderUrl: 'https://docs.example.org/PLACEHOLDER' }; +window.oc_capabilities = { +} /* jshint camelcase: true */ diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index 67b7d77be6c..63c02048a34 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -573,6 +573,10 @@ describe('Core base tests', function() { }); it('Clicking menu toggle toggles navigation in', function() { window.initCore(); + // fore show more apps icon since otherwise it would be hidden since no icons are available + clock.tick(1 * 1000); + $('#more-apps').show(); + expect($navigation.is(':visible')).toEqual(false); $toggle.click(); clock.tick(1 * 1000); diff --git a/core/js/tests/specs/sharedialoglinkshareview.js b/core/js/tests/specs/sharedialoglinkshareview.js index 9d07dcb479d..c2d84fd2e87 100644 --- a/core/js/tests/specs/sharedialoglinkshareview.js +++ b/core/js/tests/specs/sharedialoglinkshareview.js @@ -72,6 +72,102 @@ describe('OC.Share.ShareDialogLinkShareView', function () { configModel.isShareWithLinkAllowed.restore(); }); + describe('hide download', function () { + + var $hideDownloadCheckbox; + var $workingIcon; + + beforeEach(function () { + // Needed to render the view + configModel.isShareWithLinkAllowed.returns(true); + + shareModel.set({ + linkShares: [{ + id: 123 + }] + }); + view.render(); + + $hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox'); + $workingIcon = $hideDownloadCheckbox.prev('.icon-loading-small'); + + sinon.stub(shareModel, 'saveLinkShare'); + + expect($workingIcon.hasClass('hidden')).toBeTruthy(); + }); + + afterEach(function () { + shareModel.saveLinkShare.restore(); + }); + + it('is shown if the share is a file', function() { + expect($hideDownloadCheckbox.length).toBeTruthy(); + }); + + it('is not shown if the share is a folder', function() { + shareModel.fileInfoModel.set('mimetype', 'httpd/unix-directory'); + + // Setting the item type also triggers the rendering + shareModel.set({ + itemType: 'folder' + }); + + $hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox'); + + expect($hideDownloadCheckbox.length).toBeFalsy(); + }); + + it('checkbox is checked when the setting is enabled', function () { + shareModel.set({ + linkShares: [{ + id: 123, + hideDownload: true + }] + }); + view.render(); + + $hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox'); + + expect($hideDownloadCheckbox.is(':checked')).toEqual(true); + }); + + it('checkbox is not checked when the setting is disabled', function () { + expect($hideDownloadCheckbox.is(':checked')).toEqual(false); + }); + + it('enables the setting if clicked when unchecked', function () { + // Simulate the click by checking the checkbox and then triggering + // the "change" event. + $hideDownloadCheckbox.prop('checked', true); + $hideDownloadCheckbox.change(); + + expect($workingIcon.hasClass('hidden')).toBeFalsy(); + expect(shareModel.saveLinkShare.withArgs({ hideDownload: true, cid: 123 }).calledOnce).toBeTruthy(); + }); + + it('disables the setting if clicked when checked', function () { + shareModel.set({ + linkShares: [{ + id: 123, + hideDownload: true + }] + }); + view.render(); + + $hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox'); + $workingIcon = $hideDownloadCheckbox.prev('.icon-loading-small'); + + // Simulate the click by unchecking the checkbox and then triggering + // the "change" event. + $hideDownloadCheckbox.prop('checked', false); + $hideDownloadCheckbox.change(); + + expect($workingIcon.hasClass('hidden')).toBeFalsy(); + expect(shareModel.saveLinkShare.withArgs({ hideDownload: false, cid: 123 }).calledOnce).toBeTruthy(); + }); + + }); + describe('onPasswordEntered', function () { var $passwordText; @@ -82,13 +178,13 @@ describe('OC.Share.ShareDialogLinkShareView', function () { // Needed to render the view configModel.isShareWithLinkAllowed.returns(true); - // Setting the share also triggers the rendering shareModel.set({ - linkShare: { - isLinkShare: true, + linkShares: [{ + id: 123, password: 'password' - } + }] }); + view.render(); var $passwordDiv = view.$el.find('#linkPass'); $passwordText = view.$el.find('.linkPassText'); @@ -108,17 +204,17 @@ describe('OC.Share.ShareDialogLinkShareView', function () { }); it('shows the working icon when called', function () { - view.onPasswordEntered(); + view.onPasswordEntered({target: view.$el.find('.linkPassText')}); expect($workingIcon.hasClass('hidden')).toBeFalsy(); - expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword' }).calledOnce).toBeTruthy(); + expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword', cid: 123 }).calledOnce).toBeTruthy(); }); it('hides the working icon when saving the password succeeds', function () { - view.onPasswordEntered(); + view.onPasswordEntered({target: view.$el.find('.linkPassText')}); expect($workingIcon.hasClass('hidden')).toBeFalsy(); - expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword' }).calledOnce).toBeTruthy(); + expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword', cid: 123 }).calledOnce).toBeTruthy(); shareModel.saveLinkShare.yieldTo("complete", [shareModel]); @@ -126,10 +222,10 @@ describe('OC.Share.ShareDialogLinkShareView', function () { }); it('hides the working icon when saving the password fails', function () { - view.onPasswordEntered(); + view.onPasswordEntered({target: view.$el.find('.linkPassText')}); expect($workingIcon.hasClass('hidden')).toBeFalsy(); - expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword' }).calledOnce).toBeTruthy(); + expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword', cid: 123 }).calledOnce).toBeTruthy(); shareModel.saveLinkShare.yieldTo("complete", [shareModel]); shareModel.saveLinkShare.yieldTo("error", [shareModel, "The error message"]); @@ -139,4 +235,117 @@ describe('OC.Share.ShareDialogLinkShareView', function () { }); + describe('protect password by Talk', function () { + + var $passwordByTalkCheckbox; + var $workingIcon; + + beforeEach(function () { + // Needed to render the view + configModel.isShareWithLinkAllowed.returns(true); + + // "Enable" Talk + window.oc_appswebroots['spreed'] = window.oc_webroot + '/apps/files/'; + + shareModel.set({ + linkShares: [{ + id: 123, + password: 'password' + }] + }); + view.render(); + + $passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox'); + $workingIcon = $passwordByTalkCheckbox.prev('.icon-loading-small'); + + sinon.stub(shareModel, 'saveLinkShare'); + + expect($workingIcon.hasClass('hidden')).toBeTruthy(); + }); + + afterEach(function () { + shareModel.saveLinkShare.restore(); + }); + + it('is shown if Talk is enabled and there is a password set', function() { + expect($passwordByTalkCheckbox.length).toBeTruthy(); + }); + + it('is not shown if Talk is enabled but there is no password set', function() { + // Changing the password value also triggers the rendering + shareModel.set({ + linkShares: [{ + id: 123 + }] + }); + + $passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox'); + + expect($passwordByTalkCheckbox.length).toBeFalsy(); + }); + + it('is not shown if there is a password set but Talk is not enabled', function() { + // "Disable" Talk + delete window.oc_appswebroots['spreed']; + + view.render(); + + $passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox'); + + expect($passwordByTalkCheckbox.length).toBeFalsy(); + }); + + it('checkbox is checked when the setting is enabled', function () { + shareModel.set({ + linkShares: [{ + id: 123, + password: 'password', + sendPasswordByTalk: true + }] + }); + view.render(); + + $passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox'); + + expect($passwordByTalkCheckbox.is(':checked')).toEqual(true); + }); + + it('checkbox is not checked when the setting is disabled', function () { + expect($passwordByTalkCheckbox.is(':checked')).toEqual(false); + }); + + it('enables the setting if clicked when unchecked', function () { + // Simulate the click by checking the checkbox and then triggering + // the "change" event. + $passwordByTalkCheckbox.prop('checked', true); + $passwordByTalkCheckbox.change(); + + expect($workingIcon.hasClass('hidden')).toBeFalsy(); + expect(shareModel.saveLinkShare.withArgs({ sendPasswordByTalk: true, cid: 123 }).calledOnce).toBeTruthy(); + }); + + it('disables the setting if clicked when checked', function () { + shareModel.set({ + linkShares: [{ + id: 123, + password: 'password', + sendPasswordByTalk: true + }] + }); + view.render(); + + $passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox'); + $workingIcon = $passwordByTalkCheckbox.prev('.icon-loading-small'); + + // Simulate the click by unchecking the checkbox and then triggering + // the "change" event. + $passwordByTalkCheckbox.prop('checked', false); + $passwordByTalkCheckbox.change(); + + expect($workingIcon.hasClass('hidden')).toBeFalsy(); + expect(shareModel.saveLinkShare.withArgs({ sendPasswordByTalk: false, cid: 123 }).calledOnce).toBeTruthy(); + }); + + }); + }); diff --git a/core/js/tests/specs/sharedialogshareelistview.js b/core/js/tests/specs/sharedialogshareelistview.js index 8e34225d199..4f84fa0e08f 100644 --- a/core/js/tests/specs/sharedialogshareelistview.js +++ b/core/js/tests/specs/sharedialogshareelistview.js @@ -73,7 +73,7 @@ describe('OC.Share.ShareDialogShareeListView', function () { $('#testArea').append(listView.$el); shareModel.set({ - linkShare: {isLinkShare: false} + linkShares: [] }); oldCurrentUser = OC.currentUser; @@ -90,6 +90,37 @@ describe('OC.Share.ShareDialogShareeListView', function () { }); describe('Sets correct initial checkbox state', function () { + + it('marks edit box as unchecked for file shares without edit permissions', function () { + shareModel.set('shares', [{ + id: 100, + item_source: 123, + permissions: 1, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + share_with_displayname: 'User One', + uid_owner: oc_current_user, + itemType: 'file' + }]); + listView.render(); + expect(listView.$el.find("input[name='edit']").is(':not(:checked)')).toEqual(true); + }); + + it('marks edit box as checked for file shares', function () { + shareModel.set('shares', [{ + id: 100, + item_source: 123, + permissions: 1 | OC.PERMISSION_UPDATE, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + share_with_displayname: 'User One', + uid_owner: oc_current_user, + itemType: 'file' + }]); + listView.render(); + expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true); + }); + it('marks edit box as indeterminate when only some permissions are given', function () { shareModel.set('shares', [{ id: 100, diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js index efe50c415c8..8d5a2ae434d 100644 --- a/core/js/tests/specs/sharedialogviewSpec.js +++ b/core/js/tests/specs/sharedialogviewSpec.js @@ -89,7 +89,7 @@ describe('OC.Share.ShareDialogView', function() { // triggers rendering shareModel.set({ shares: [], - linkShare: {isLinkShare: false} + linkShares: [] }); autocompleteStub = sinon.stub($.fn, 'autocomplete').callsFake(function() { @@ -130,8 +130,10 @@ describe('OC.Share.ShareDialogView', function() { it('update password on focus out', function() { $('#allowShareWithLink').val('yes'); - dialog.model.set('linkShare', { - isLinkShare: true + dialog.model.set({ + linkShares: [{ + id: 123 + }] }); dialog.render(); @@ -143,20 +145,20 @@ describe('OC.Share.ShareDialogView', function() { expect(saveLinkShareStub.calledOnce).toEqual(true); expect(saveLinkShareStub.firstCall.args[0]).toEqual({ + cid: 123, password: 'foo' }); }); it('update password on enter', function() { $('#allowShareWithLink').val('yes'); - dialog.model.set('linkShare', { - isLinkShare: true + dialog.model.set({ + linkShares: [{ + id: 123 + }] }); dialog.render(); - // Toggle linkshare - dialog.$el.find('.linkCheckbox').click(); - // Enable password and enter password dialog.$el.find('[name=showPassword]').click(); dialog.$el.find('.linkPassText').focus(); @@ -165,47 +167,48 @@ describe('OC.Share.ShareDialogView', function() { expect(saveLinkShareStub.calledOnce).toEqual(true); expect(saveLinkShareStub.firstCall.args[0]).toEqual({ + cid: 123, password: 'foo' }); }); - it('shows share with link checkbox when allowed', function() { + it('shows add share with link button when allowed', function() { $('#allowShareWithLink').val('yes'); dialog.render(); - expect(dialog.$el.find('.linkCheckbox').length).toEqual(1); + expect(dialog.$el.find('.new-share').length).toEqual(1); }); - it('does not show share with link checkbox when not allowed', function() { + it('does not show add share with link button when not allowed', function() { $('#allowShareWithLink').val('no'); dialog.render(); - expect(dialog.$el.find('.linkCheckbox').length).toEqual(0); + expect(dialog.$el.find('.new-share').length).toEqual(0); expect(dialog.$el.find('.shareWithField').length).toEqual(1); }); it('shows populated link share when a link share exists', function() { // this is how the OC.Share class does it... var link = parent.location.protocol + '//' + location.host + - OC.generateUrl('/s/') + 'tehtoken'; - shareModel.set('linkShare', { - isLinkShare: true, - token: 'tehtoken', - link: link, - expiration: '', - permissions: OC.PERMISSION_READ, - stime: 1403884258, + OC.generateUrl('/s/') + 'thetoken'; + shareModel.set({ + linkShares: [{ + id: 123, + url: link + }] }); dialog.render(); - expect(dialog.$el.find('.linkCheckbox').prop('checked')).toEqual(true); + expect(dialog.$el.find('.share-menu .icon-more').length).toEqual(1); expect(dialog.$el.find('.linkText').val()).toEqual(link); }); it('autofocus link text when clicked', function() { $('#allowShareWithLink').val('yes'); - dialog.model.set('linkShare', { - isLinkShare: true + dialog.model.set({ + linkShares: [{ + id: 123 + }] }); dialog.render(); diff --git a/core/js/tests/specs/shareitemmodelSpec.js b/core/js/tests/specs/shareitemmodelSpec.js index 2e89b2e3cda..e8016950094 100644 --- a/core/js/tests/specs/shareitemmodelSpec.js +++ b/core/js/tests/specs/shareitemmodelSpec.js @@ -168,7 +168,9 @@ describe('OC.Share.ShareItemModel', function() { stime: 1403884258, storage: 1, token: 'tehtoken', - uid_owner: 'root' + uid_owner: 'root', + hide_download: 1, + send_password_by_talk: true } ])); @@ -184,8 +186,11 @@ describe('OC.Share.ShareItemModel', function() { expect(shares[0].share_with).toEqual('user1'); expect(shares[0].share_with_displayname).toEqual('User One'); - var linkShare = model.get('linkShare'); - expect(linkShare.isLinkShare).toEqual(true); + var linkShares = model.get('linkShares'); + expect(linkShares.length).toEqual(1); + var linkShare = linkShares[0]; + expect(linkShare.hideDownload).toEqual(true); + expect(linkShare.sendPasswordByTalk).toEqual(true); // TODO: check more attributes }); @@ -266,8 +271,8 @@ describe('OC.Share.ShareItemModel', function() { // remaining share appears in this list expect(shares.length).toEqual(1); - var linkShare = model.get('linkShare'); - expect(linkShare.isLinkShare).toEqual(false); + var linkShares = model.get('linkShares'); + expect(linkShares.length).toEqual(0); }); it('parses correct link share when a nested link share exists along with parent one', function() { /* jshint camelcase: false */ @@ -289,7 +294,9 @@ describe('OC.Share.ShareItemModel', function() { stime: 1403884258, storage: 1, token: 'tehtoken', - uid_owner: 'root' + uid_owner: 'root', + hide_download: 0, + send_password_by_talk: false }, { displayname_owner: 'root', expiration: '2015-10-15 00:00:00', @@ -307,7 +314,9 @@ describe('OC.Share.ShareItemModel', function() { stime: 1403884509, storage: 1, token: 'anothertoken', - uid_owner: 'root' + uid_owner: 'root', + hide_download: 1, + send_password_by_talk: true }] )); OC.currentUser = 'root'; @@ -317,9 +326,12 @@ describe('OC.Share.ShareItemModel', function() { // the parent share remains in the list expect(shares.length).toEqual(1); - var linkShare = model.get('linkShare'); - expect(linkShare.isLinkShare).toEqual(true); + var linkShares = model.get('linkShares'); + expect(linkShares.length).toEqual(1); + var linkShare = linkShares[0]; expect(linkShare.token).toEqual('tehtoken'); + expect(linkShare.hideDownload).toEqual(false); + expect(linkShare.sendPasswordByTalk).toEqual(false); // TODO: check child too }); @@ -570,17 +582,18 @@ describe('OC.Share.ShareItemModel', function() { it('creates a new share if no link share exists', function() { model.set({ - linkShare: { - isLinkShare: false - } + linkShares: [ + ] }); model.saveLinkShare(); expect(addShareStub.calledOnce).toEqual(true); expect(addShareStub.firstCall.args[0]).toEqual({ + hideDownload: false, password: '', passwordChanged: false, + sendPasswordByTalk: false, permissions: OC.PERMISSION_READ, expireDate: '', shareType: OC.Share.SHARE_TYPE_LINK @@ -594,17 +607,18 @@ describe('OC.Share.ShareItemModel', function() { defaultExpireDate: 7 }); model.set({ - linkShare: { - isLinkShare: false - } + linkShares: [ + ] }); model.saveLinkShare(); expect(addShareStub.calledOnce).toEqual(true); expect(addShareStub.firstCall.args[0]).toEqual({ + hideDownload: false, password: '', passwordChanged: false, + sendPasswordByTalk: false, permissions: OC.PERMISSION_READ, expireDate: '2015-07-24 00:00:00', shareType: OC.Share.SHARE_TYPE_LINK @@ -614,13 +628,13 @@ describe('OC.Share.ShareItemModel', function() { }); it('updates link share if it exists', function() { model.set({ - linkShare: { - isLinkShare: true, + linkShares: [{ id: 123 - } + }] }); model.saveLinkShare({ + cid: 123, password: 'test' }); @@ -628,20 +642,19 @@ describe('OC.Share.ShareItemModel', function() { expect(updateShareStub.calledOnce).toEqual(true); expect(updateShareStub.firstCall.args[0]).toEqual(123); expect(updateShareStub.firstCall.args[1]).toEqual({ + cid: 123, password: 'test' }); }); it('forwards error message on add', function() { var errorStub = sinon.stub(); model.set({ - linkShare: { - isLinkShare: false - } + linkShares: [ + ] }, { }); model.saveLinkShare({ - password: 'test' }, { error: errorStub }); @@ -654,14 +667,14 @@ describe('OC.Share.ShareItemModel', function() { it('forwards error message on update', function() { var errorStub = sinon.stub(); model.set({ - linkShare: { - isLinkShare: true, - id: '123' - } + linkShares: [{ + id: 123 + }] }, { }); model.saveLinkShare({ + cid: 123, password: 'test' }, { error: errorStub diff --git a/core/l10n/af.js b/core/l10n/af.js index f8088145682..8fc043f81b4 100644 --- a/core/l10n/af.js +++ b/core/l10n/af.js @@ -118,7 +118,9 @@ OC.L10N.register( "Set expiration date" : "Stel vervaldatum", "Expiration" : "Verval", "Expiration date" : "Vervaldatum", + "Unshare" : "Ontdeel", "Share link" : "Deel skakel", + "Could not unshare" : "Kon nie ontdeel nie", "Shared with you and the group {group} by {owner}" : "Gedeel met u en die groep {group} deur {owner}", "Shared with you by {owner}" : "Gedeel met u deur {owner}", "Choose a password for the mail share" : "Kies 'n wagwoord vir die e-pos lêer deel ", @@ -126,14 +128,12 @@ OC.L10N.register( "remote" : "afgeleë", "email" : "e-pos", "shared by {sharer}" : "gedeel deur {sharer}", - "Unshare" : "Ontdeel", "Can reshare" : "Kan herdeel", "Can edit" : "Kan redigeer", "Can create" : "Kan skep", "Can change" : "Kan verander", "Can delete" : "Kan skrap", "Access control" : "Toegangsbeheer", - "Could not unshare" : "Kon nie ontdeel nie", "Error while sharing" : "Fout terwyl deel", "Share details could not be loaded for this item." : "Deel besonderhede kon nie vir die item gelaai word nie.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Ten minste {count} karakter word benodig vir outomatiese aanvulling","Ten minste {count} karakters word benodig vir outomatiese aanvulling"], @@ -141,9 +141,6 @@ OC.L10N.register( "No users found for {search}" : "Geen gebruiker gevind vir {search}", "An error occurred (\"{message}\"). Please try again" : "'n Fout het voorgekom (\"{message}\"). Probeer asseblief weer", "An error occurred. Please try again" : "'n Fout het voorgekom. Probeer asseblief weer", - "{sharee} (group)" : "{sharee} (groep)", - "{sharee} (remote)" : "{sharee} (afgeleë)", - "{sharee} (email)" : "{sharee} (e-pos)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Deel", "Name or email address..." : "Naam of e-posadres...", @@ -243,6 +240,9 @@ OC.L10N.register( "Error setting expiration date" : "Fout terwyl vervaldatum stel", "The public link will expire no later than {days} days after it is created" : "Die publieke skakel sal presies {days} na dit geskep is verval", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} gedeel via skakel", + "{sharee} (group)" : "{sharee} (groep)", + "{sharee} (remote)" : "{sharee} (afgeleë)", + "{sharee} (email)" : "{sharee} (e-pos)", "Share with other people by entering a user or group or an email address." : "Deel met ander deur 'n gebruiker, groep of e-posadres in te vul. ", "The specified document has not been found on the server." : "Die gekose dokument was nie op die bediener gevind nie.", "You can click here to return to %s." : "U kan hier klik om terug te keer na %s", diff --git a/core/l10n/af.json b/core/l10n/af.json index e835f8bf954..48993b7b7c1 100644 --- a/core/l10n/af.json +++ b/core/l10n/af.json @@ -116,7 +116,9 @@ "Set expiration date" : "Stel vervaldatum", "Expiration" : "Verval", "Expiration date" : "Vervaldatum", + "Unshare" : "Ontdeel", "Share link" : "Deel skakel", + "Could not unshare" : "Kon nie ontdeel nie", "Shared with you and the group {group} by {owner}" : "Gedeel met u en die groep {group} deur {owner}", "Shared with you by {owner}" : "Gedeel met u deur {owner}", "Choose a password for the mail share" : "Kies 'n wagwoord vir die e-pos lêer deel ", @@ -124,14 +126,12 @@ "remote" : "afgeleë", "email" : "e-pos", "shared by {sharer}" : "gedeel deur {sharer}", - "Unshare" : "Ontdeel", "Can reshare" : "Kan herdeel", "Can edit" : "Kan redigeer", "Can create" : "Kan skep", "Can change" : "Kan verander", "Can delete" : "Kan skrap", "Access control" : "Toegangsbeheer", - "Could not unshare" : "Kon nie ontdeel nie", "Error while sharing" : "Fout terwyl deel", "Share details could not be loaded for this item." : "Deel besonderhede kon nie vir die item gelaai word nie.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Ten minste {count} karakter word benodig vir outomatiese aanvulling","Ten minste {count} karakters word benodig vir outomatiese aanvulling"], @@ -139,9 +139,6 @@ "No users found for {search}" : "Geen gebruiker gevind vir {search}", "An error occurred (\"{message}\"). Please try again" : "'n Fout het voorgekom (\"{message}\"). Probeer asseblief weer", "An error occurred. Please try again" : "'n Fout het voorgekom. Probeer asseblief weer", - "{sharee} (group)" : "{sharee} (groep)", - "{sharee} (remote)" : "{sharee} (afgeleë)", - "{sharee} (email)" : "{sharee} (e-pos)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Deel", "Name or email address..." : "Naam of e-posadres...", @@ -241,6 +238,9 @@ "Error setting expiration date" : "Fout terwyl vervaldatum stel", "The public link will expire no later than {days} days after it is created" : "Die publieke skakel sal presies {days} na dit geskep is verval", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} gedeel via skakel", + "{sharee} (group)" : "{sharee} (groep)", + "{sharee} (remote)" : "{sharee} (afgeleë)", + "{sharee} (email)" : "{sharee} (e-pos)", "Share with other people by entering a user or group or an email address." : "Deel met ander deur 'n gebruiker, groep of e-posadres in te vul. ", "The specified document has not been found on the server." : "Die gekose dokument was nie op die bediener gevind nie.", "You can click here to return to %s." : "U kan hier klik om terug te keer na %s", diff --git a/core/l10n/ast.js b/core/l10n/ast.js index d40d4138279..fd629d66a6a 100644 --- a/core/l10n/ast.js +++ b/core/l10n/ast.js @@ -111,27 +111,25 @@ OC.L10N.register( "Set expiration date" : "Afitar la data de caducidá", "Expiration" : "Caducidá", "Expiration date" : "Data de caducidá", + "Unshare" : "Dexar de compartir", "Share link" : "Compartir enllaz", + "Could not unshare" : "Nun pudo dexar de compartise", "Shared with you and the group {group} by {owner}" : "Compartíu contigo y col grupu {group} por {owner}", "Shared with you by {owner}" : "Compartíu contigo por {owner}", "group" : "grupu", "remote" : "remotu", "email" : "corréu", - "Unshare" : "Dexar de compartir", "Can edit" : "Pue editar", "Can create" : "Pue crear", "Can change" : "Pue camudar", "Can delete" : "Pue desaniciar", "Access control" : "Control d'accesu", - "Could not unshare" : "Nun pudo dexar de compartise", "Error while sharing" : "Fallu mientres la compartición", "Share details could not be loaded for this item." : "Nun pudieron cargase los detalles de la compartición pa esti elementu.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Precísase polo menos {count} caráuter pal auto-completáu","Precísense polo menos {count} caráuteres pal auto-completáu"], "No users or groups found for {search}" : "Nun s'alcontraron usuarios o grupos pa {search}", "No users found for {search}" : "Nun s'alcontraron usuarios pa {search}", "An error occurred. Please try again" : "Asocedió un fallu. Volvi tentalo, por favor", - "{sharee} (group)" : "{sharee} (grupu)", - "{sharee} (email)" : "{sharee} (corréu)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nome o direición de corréu...", @@ -230,6 +228,8 @@ OC.L10N.register( "Error setting expiration date" : "Fallu afitando la fecha de caducidá", "The public link will expire no later than {days} days after it is created" : "L'enllaz públicu va caducar enantes de {days} díes dende la so creación", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} compartió per enllaz", + "{sharee} (group)" : "{sharee} (grupu)", + "{sharee} (email)" : "{sharee} (corréu)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparti con otra xente introduciendo un usuariu, grupu, ID de ñube federada o direición de corréu.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparti con otra xente introduciendo un usuariu, grupu o ID de ñube federada.", "Share with other people by entering a user or group or an email address." : "Comparti con otra xente introduciendo un usuariu, grupu o direición de corréu.", diff --git a/core/l10n/ast.json b/core/l10n/ast.json index 5019fcc9955..0f493ffd0e3 100644 --- a/core/l10n/ast.json +++ b/core/l10n/ast.json @@ -109,27 +109,25 @@ "Set expiration date" : "Afitar la data de caducidá", "Expiration" : "Caducidá", "Expiration date" : "Data de caducidá", + "Unshare" : "Dexar de compartir", "Share link" : "Compartir enllaz", + "Could not unshare" : "Nun pudo dexar de compartise", "Shared with you and the group {group} by {owner}" : "Compartíu contigo y col grupu {group} por {owner}", "Shared with you by {owner}" : "Compartíu contigo por {owner}", "group" : "grupu", "remote" : "remotu", "email" : "corréu", - "Unshare" : "Dexar de compartir", "Can edit" : "Pue editar", "Can create" : "Pue crear", "Can change" : "Pue camudar", "Can delete" : "Pue desaniciar", "Access control" : "Control d'accesu", - "Could not unshare" : "Nun pudo dexar de compartise", "Error while sharing" : "Fallu mientres la compartición", "Share details could not be loaded for this item." : "Nun pudieron cargase los detalles de la compartición pa esti elementu.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Precísase polo menos {count} caráuter pal auto-completáu","Precísense polo menos {count} caráuteres pal auto-completáu"], "No users or groups found for {search}" : "Nun s'alcontraron usuarios o grupos pa {search}", "No users found for {search}" : "Nun s'alcontraron usuarios pa {search}", "An error occurred. Please try again" : "Asocedió un fallu. Volvi tentalo, por favor", - "{sharee} (group)" : "{sharee} (grupu)", - "{sharee} (email)" : "{sharee} (corréu)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nome o direición de corréu...", @@ -228,6 +226,8 @@ "Error setting expiration date" : "Fallu afitando la fecha de caducidá", "The public link will expire no later than {days} days after it is created" : "L'enllaz públicu va caducar enantes de {days} díes dende la so creación", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} compartió per enllaz", + "{sharee} (group)" : "{sharee} (grupu)", + "{sharee} (email)" : "{sharee} (corréu)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparti con otra xente introduciendo un usuariu, grupu, ID de ñube federada o direición de corréu.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparti con otra xente introduciendo un usuariu, grupu o ID de ñube federada.", "Share with other people by entering a user or group or an email address." : "Comparti con otra xente introduciendo un usuariu, grupu o direición de corréu.", diff --git a/core/l10n/bg.js b/core/l10n/bg.js index 08eea88b739..b974358684c 100644 --- a/core/l10n/bg.js +++ b/core/l10n/bg.js @@ -127,8 +127,9 @@ OC.L10N.register( "Expiration" : "Валидност", "Expiration date" : "Дата на изтичане", "Note to recipient" : "Бележка за получателя", + "Unshare" : "Прекрати споделянето", "Share link" : "Връзка за споделяне", - "Enable" : "Включена", + "Could not unshare" : "Споделянето не може да бъде прекратено", "Shared with you and the group {group} by {owner}" : "Споделено от {owner} с вас и групата {group}", "Shared with you in a conversation by {owner}" : "Споделено с вас в разговор от {owner}", "Shared with you by {owner}" : "Споделено с вас от {owner}", @@ -138,25 +139,19 @@ OC.L10N.register( "email" : "имейл", "conversation" : "разговор", "shared by {sharer}" : "споделено от {sharer}", - "Unshare" : "Прекрати споделянето", "Can reshare" : "Може да споделя повторно", "Can edit" : "Може да редактира", "Can create" : "Може да създава", "Can change" : "Може да променя", "Can delete" : "Може да изтрива", "Access control" : "Контрол на достъпа", - "Could not unshare" : "Споделянето не може да бъде прекратено", "Error while sharing" : "Грешка при споделяне", "Share details could not be loaded for this item." : "Данните за споделяне не могат да бъдат заредени", "No users or groups found for {search}" : "Няма потребители или групи за {search}", "No users found for {search}" : "Няма потребители за {search}", "An error occurred. Please try again" : "Възникна грешка. Моля, опитайте отново", - "{sharee} (group)" : "{sharee} (група)", - "{sharee} (remote)" : "{sharee} (отдалечен)", "{sharee} (remote group)" : "{sharee} (отдалечена група)", - "{sharee} (email)" : "{sharee} (имейл)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (разговор)", "Share" : "Споделяне", "Name or email address..." : "Име или имейл адрес...", "Name..." : "Име...", @@ -278,6 +273,9 @@ OC.L10N.register( "Error setting expiration date" : "Грешка при задаване на срок на валидност", "The public link will expire no later than {days} days after it is created" : "Общодостъпната връзка ще изтече не по-късно от {days} дни след създаването ѝ.", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} споделен с връзка", + "{sharee} (group)" : "{sharee} (група)", + "{sharee} (remote)" : "{sharee} (отдалечен)", + "{sharee} (email)" : "{sharee} (имейл)", "The specified document has not been found on the server." : "Избраният документ не е намерен на сървъра.", "You can click here to return to %s." : "Можете да натиснете тук, за да се върнете на %s.", "The server encountered an internal error and was unable to complete your request." : "Поради вътрешно сървърна грешка, сървърът не можа да изпълни заявката ви.", @@ -297,6 +295,8 @@ OC.L10N.register( "This page will refresh itself when the %s instance is available again." : "Страницата ще се зареди автоматично, когато %s е отново на линия.", "Thank you for your patience." : "Благодарим ви за търпението.", "You are about to grant %s access to your %s account." : "Ще разрешите на %s да ползва профила %s.", + "Enable" : "Включена", + "{sharee} (conversation)" : "{sharee} (разговор)", "Please log in before granting %s access to your %s account." : "Необходимо е да се впишете, преди да дадете достъп на %s до вашия %s профил." }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/bg.json b/core/l10n/bg.json index 7b2368f8d99..53c06c23041 100644 --- a/core/l10n/bg.json +++ b/core/l10n/bg.json @@ -125,8 +125,9 @@ "Expiration" : "Валидност", "Expiration date" : "Дата на изтичане", "Note to recipient" : "Бележка за получателя", + "Unshare" : "Прекрати споделянето", "Share link" : "Връзка за споделяне", - "Enable" : "Включена", + "Could not unshare" : "Споделянето не може да бъде прекратено", "Shared with you and the group {group} by {owner}" : "Споделено от {owner} с вас и групата {group}", "Shared with you in a conversation by {owner}" : "Споделено с вас в разговор от {owner}", "Shared with you by {owner}" : "Споделено с вас от {owner}", @@ -136,25 +137,19 @@ "email" : "имейл", "conversation" : "разговор", "shared by {sharer}" : "споделено от {sharer}", - "Unshare" : "Прекрати споделянето", "Can reshare" : "Може да споделя повторно", "Can edit" : "Може да редактира", "Can create" : "Може да създава", "Can change" : "Може да променя", "Can delete" : "Може да изтрива", "Access control" : "Контрол на достъпа", - "Could not unshare" : "Споделянето не може да бъде прекратено", "Error while sharing" : "Грешка при споделяне", "Share details could not be loaded for this item." : "Данните за споделяне не могат да бъдат заредени", "No users or groups found for {search}" : "Няма потребители или групи за {search}", "No users found for {search}" : "Няма потребители за {search}", "An error occurred. Please try again" : "Възникна грешка. Моля, опитайте отново", - "{sharee} (group)" : "{sharee} (група)", - "{sharee} (remote)" : "{sharee} (отдалечен)", "{sharee} (remote group)" : "{sharee} (отдалечена група)", - "{sharee} (email)" : "{sharee} (имейл)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (разговор)", "Share" : "Споделяне", "Name or email address..." : "Име или имейл адрес...", "Name..." : "Име...", @@ -276,6 +271,9 @@ "Error setting expiration date" : "Грешка при задаване на срок на валидност", "The public link will expire no later than {days} days after it is created" : "Общодостъпната връзка ще изтече не по-късно от {days} дни след създаването ѝ.", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} споделен с връзка", + "{sharee} (group)" : "{sharee} (група)", + "{sharee} (remote)" : "{sharee} (отдалечен)", + "{sharee} (email)" : "{sharee} (имейл)", "The specified document has not been found on the server." : "Избраният документ не е намерен на сървъра.", "You can click here to return to %s." : "Можете да натиснете тук, за да се върнете на %s.", "The server encountered an internal error and was unable to complete your request." : "Поради вътрешно сървърна грешка, сървърът не можа да изпълни заявката ви.", @@ -295,6 +293,8 @@ "This page will refresh itself when the %s instance is available again." : "Страницата ще се зареди автоматично, когато %s е отново на линия.", "Thank you for your patience." : "Благодарим ви за търпението.", "You are about to grant %s access to your %s account." : "Ще разрешите на %s да ползва профила %s.", + "Enable" : "Включена", + "{sharee} (conversation)" : "{sharee} (разговор)", "Please log in before granting %s access to your %s account." : "Необходимо е да се впишете, преди да дадете достъп на %s до вашия %s профил." },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/core/l10n/ca.js b/core/l10n/ca.js index e6ae31313df..87db749cf63 100644 --- a/core/l10n/ca.js +++ b/core/l10n/ca.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Activat el mode de manteniment", "Turned off maintenance mode" : "Desactivat el mode de manteniment", "Maintenance mode is kept active" : "El mode de manteniment es manté activat", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Esperant cron per acabar (torna a comprovar en 5 segons) …", "Updating database schema" : "Actualitzant l'esquema de la base de dades", "Updated database" : "Actualitzada la base de dades", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Comprovar si l'esquema de base de dades es pot actualitzar (això pot trigar temps segons la mida de la base de dades)", @@ -160,12 +159,12 @@ OC.L10N.register( "Choose a password for the public link" : "Escolliu una contrasenya per l'enllaç públic", "Choose a password for the public link or press the \"Enter\" key" : "Escolliu una contrasenya per l'enllaç públic o premeu la tecla \"Enter\"", "Copied!" : "Copiat!", + "Copy link" : "Copiar enllaç", "Not supported!" : "No soportat!", "Press ⌘-C to copy." : "Prem ⌘-C per copiar.", "Press Ctrl-C to copy." : "Prem Ctrl-C per copiar.", "Resharing is not allowed" : "No es permet compartir de nou", "Share to {name}" : "Comparteix amb {name}", - "Copy link" : "Copiar enllaç", "Link" : "Enllaç", "Password protect" : "Protegir amb contrasenya", "Allow editing" : "Permetre edició", @@ -178,8 +177,10 @@ OC.L10N.register( "Expiration" : "Expiració", "Expiration date" : "Data de venciment", "Note to recipient" : "Nota a destinatari", + "Unshare" : "Deixa de compartir", "Share link" : "Enllaç de compartició", - "Enable" : "Habilitar", + "Password protect by Talk" : "Contrasenya protegida per Talk", + "Could not unshare" : "No pot descompartir", "Shared with you and the group {group} by {owner}" : "Compartit amb vos i amb el grup {group} per {owner}", "Shared with you and {circle} by {owner}" : "Compartit amb tu i {circle} per {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Compartit amb tu i amb la conversa {conversation} per {owner}", @@ -192,16 +193,13 @@ OC.L10N.register( "email" : "email", "conversation" : "conversa", "shared by {sharer}" : "compartit per {sharer}", - "Unshare" : "Deixa de compartir", "Can reshare" : "Pot recompartir", "Can edit" : "Pot editar", "Can create" : "Pot crear", "Can change" : "Pot modificar", "Can delete" : "Pot esborrar", - "Password protect by Talk" : "Contrasenya protegida per Talk", "Access control" : "Control d'accés", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} compartida per enllaç", - "Could not unshare" : "No pot descompartir", "Error while sharing" : "Error en compartir", "Share details could not be loaded for this item." : "No s'han pogut carregar els detalls de compartició de l'element.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Com a mínim cal {count} caràcter per a l'autocompletat","Com a mínim calen {count} caràcters per a l'autocompletat"], @@ -210,12 +208,8 @@ OC.L10N.register( "No users found for {search}" : "No s'han trobat usuaris per {search}", "An error occurred (\"{message}\"). Please try again" : "S'ha produït un error (\"{message}\"). Si us plau, torni a intentar-ho", "An error occurred. Please try again" : "S'ha produït un error. Si us plau, torni a intentar-ho", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (remot)", "{sharee} (remote group)" : "{sharee} (grup remot)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", "Share" : "Comparteix", "Name or email address..." : "Nom o adreça electrònica...", "Name or federated cloud ID..." : "Nom o ID de Núvol Federat…", @@ -382,6 +376,9 @@ OC.L10N.register( "Error setting expiration date" : "Error en establir la data de venciment", "The public link will expire no later than {days} days after it is created" : "L'enllaç públic tindrà venciment abans de {days} dies després de crear-lo", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartit per enllaç", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (remot)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Compartir amb altres persones introduint un usuari o grup, un ID de núvol federat o una adreça d’email.", "Share with other people by entering a user or group or a federated cloud ID." : "Compartir amb altres persones introduint un usuari o grup o ID de núvol federat.", "Share with other people by entering a user or group or an email address." : "Compartir amb altres persones introduint un usuari o grup o una adreça d’email.", @@ -413,6 +410,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Estàs a punt d'autoritzar a %s a accedir al teu compte %s.", "Depending on your configuration, this button could also work to trust the domain:" : "Depenent de la teva configuració, aquest botó també podria funcionar per confiar en el domini:", "Copy URL" : "Copiar URL", + "Enable" : "Habilitar", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Si us plau entrar abans de donar %s accés al teu compte %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Més informació de com configurar això es pot trobar a la %sdocumentation%s." }, diff --git a/core/l10n/ca.json b/core/l10n/ca.json index c166f4648db..f5155827daa 100644 --- a/core/l10n/ca.json +++ b/core/l10n/ca.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Activat el mode de manteniment", "Turned off maintenance mode" : "Desactivat el mode de manteniment", "Maintenance mode is kept active" : "El mode de manteniment es manté activat", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Esperant cron per acabar (torna a comprovar en 5 segons) …", "Updating database schema" : "Actualitzant l'esquema de la base de dades", "Updated database" : "Actualitzada la base de dades", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Comprovar si l'esquema de base de dades es pot actualitzar (això pot trigar temps segons la mida de la base de dades)", @@ -158,12 +157,12 @@ "Choose a password for the public link" : "Escolliu una contrasenya per l'enllaç públic", "Choose a password for the public link or press the \"Enter\" key" : "Escolliu una contrasenya per l'enllaç públic o premeu la tecla \"Enter\"", "Copied!" : "Copiat!", + "Copy link" : "Copiar enllaç", "Not supported!" : "No soportat!", "Press ⌘-C to copy." : "Prem ⌘-C per copiar.", "Press Ctrl-C to copy." : "Prem Ctrl-C per copiar.", "Resharing is not allowed" : "No es permet compartir de nou", "Share to {name}" : "Comparteix amb {name}", - "Copy link" : "Copiar enllaç", "Link" : "Enllaç", "Password protect" : "Protegir amb contrasenya", "Allow editing" : "Permetre edició", @@ -176,8 +175,10 @@ "Expiration" : "Expiració", "Expiration date" : "Data de venciment", "Note to recipient" : "Nota a destinatari", + "Unshare" : "Deixa de compartir", "Share link" : "Enllaç de compartició", - "Enable" : "Habilitar", + "Password protect by Talk" : "Contrasenya protegida per Talk", + "Could not unshare" : "No pot descompartir", "Shared with you and the group {group} by {owner}" : "Compartit amb vos i amb el grup {group} per {owner}", "Shared with you and {circle} by {owner}" : "Compartit amb tu i {circle} per {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Compartit amb tu i amb la conversa {conversation} per {owner}", @@ -190,16 +191,13 @@ "email" : "email", "conversation" : "conversa", "shared by {sharer}" : "compartit per {sharer}", - "Unshare" : "Deixa de compartir", "Can reshare" : "Pot recompartir", "Can edit" : "Pot editar", "Can create" : "Pot crear", "Can change" : "Pot modificar", "Can delete" : "Pot esborrar", - "Password protect by Talk" : "Contrasenya protegida per Talk", "Access control" : "Control d'accés", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} compartida per enllaç", - "Could not unshare" : "No pot descompartir", "Error while sharing" : "Error en compartir", "Share details could not be loaded for this item." : "No s'han pogut carregar els detalls de compartició de l'element.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Com a mínim cal {count} caràcter per a l'autocompletat","Com a mínim calen {count} caràcters per a l'autocompletat"], @@ -208,12 +206,8 @@ "No users found for {search}" : "No s'han trobat usuaris per {search}", "An error occurred (\"{message}\"). Please try again" : "S'ha produït un error (\"{message}\"). Si us plau, torni a intentar-ho", "An error occurred. Please try again" : "S'ha produït un error. Si us plau, torni a intentar-ho", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (remot)", "{sharee} (remote group)" : "{sharee} (grup remot)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", "Share" : "Comparteix", "Name or email address..." : "Nom o adreça electrònica...", "Name or federated cloud ID..." : "Nom o ID de Núvol Federat…", @@ -380,6 +374,9 @@ "Error setting expiration date" : "Error en establir la data de venciment", "The public link will expire no later than {days} days after it is created" : "L'enllaç públic tindrà venciment abans de {days} dies després de crear-lo", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartit per enllaç", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (remot)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Compartir amb altres persones introduint un usuari o grup, un ID de núvol federat o una adreça d’email.", "Share with other people by entering a user or group or a federated cloud ID." : "Compartir amb altres persones introduint un usuari o grup o ID de núvol federat.", "Share with other people by entering a user or group or an email address." : "Compartir amb altres persones introduint un usuari o grup o una adreça d’email.", @@ -411,6 +408,8 @@ "You are about to grant %s access to your %s account." : "Estàs a punt d'autoritzar a %s a accedir al teu compte %s.", "Depending on your configuration, this button could also work to trust the domain:" : "Depenent de la teva configuració, aquest botó també podria funcionar per confiar en el domini:", "Copy URL" : "Copiar URL", + "Enable" : "Habilitar", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Si us plau entrar abans de donar %s accés al teu compte %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Més informació de com configurar això es pot trobar a la %sdocumentation%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/cs.js b/core/l10n/cs.js index 8a0f26a4e22..b41ab810398 100644 --- a/core/l10n/cs.js +++ b/core/l10n/cs.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Zapnut režim údržby", "Turned off maintenance mode" : "Vypnut režim údržby", "Maintenance mode is kept active" : "Režim údržby je aktivní", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Čekání na dokončení cronu (zkontroluje znovu za 5 sekund)…", "Updating database schema" : "Aktualizace schéma databáze", "Updated database" : "Zaktualizována databáze", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Probíhá ověření, zda je možné aktualizovat schéma databáze (toto může trvat déle v závislosti na velikosti databáze)", @@ -160,12 +159,12 @@ OC.L10N.register( "Choose a password for the public link" : "Zadej heslo pro tento veřejný odkaz", "Choose a password for the public link or press the \"Enter\" key" : "Zvolte heslo pro veřejný odkaz nebo stiskněte klávesu „Enter“", "Copied!" : "Zkopírováno!", + "Copy link" : "Zkopírovat odkaz", "Not supported!" : "Nepodporováno!", "Press ⌘-C to copy." : "Zmáčknout ⌘-C pro kopírování.", "Press Ctrl-C to copy." : "Zmáčknout Ctrl-C pro kopírování.", "Resharing is not allowed" : "Sdílení už sdílené položky není povoleno", "Share to {name}" : "Sdílet {name}", - "Copy link" : "Zkopírovat odkaz", "Link" : "Odkaz", "Password protect" : "Chránit heslem", "Allow editing" : "Umožnit úpravy", @@ -178,8 +177,10 @@ OC.L10N.register( "Expiration" : "Konec platnosti", "Expiration date" : "Datum skončení platnosti", "Note to recipient" : "Poznámka pro příjemce", + "Unshare" : "Zrušit sdílení", "Share link" : "Odkaz pro sdílení", - "Enable" : "Povolit", + "Password protect by Talk" : "Ochrana heslem pomocí Talk", + "Could not unshare" : "Nelze zrušit sdílení", "Shared with you and the group {group} by {owner}" : "S Vámi a skupinou {group} sdílí {owner}", "Shared with you and {circle} by {owner}" : "Sdíleno s vámi a {circle} od {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Sdíleno {owner} s vámi a konverzací {conversation}", @@ -192,16 +193,13 @@ OC.L10N.register( "email" : "e-mail", "conversation" : "konverzace", "shared by {sharer}" : "Sdílel {sharer}", - "Unshare" : "Zrušit sdílení", "Can reshare" : "Může znovu sdílet", "Can edit" : "Může upravovat", "Can create" : "Může vytvářet", "Can change" : "Může měnit", "Can delete" : "Může mazat", - "Password protect by Talk" : "Ochrana heslem pomocí Talk", "Access control" : "Řízení přístupu", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} nasdílel(a) prostřednictvím odkazu", - "Could not unshare" : "Nelze zrušit sdílení", "Error while sharing" : "Chyba při sdílení", "Share details could not be loaded for this item." : "Detaily sdílení pro tuto položku nelze načíst.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Alespoň {count} znak je vyžadován pro automatické doplňování","Alespoň {count} znaky jsou vyžadovány pro automatické doplňování","Alespoň {count} znaků je vyžadováno pro automatické doplňování","Alespoň {count} znaků je vyžadováno pro automatické doplňování"], @@ -210,12 +208,8 @@ OC.L10N.register( "No users found for {search}" : "Nebyli nalezeni žádní uživatelé pro {search}", "An error occurred (\"{message}\"). Please try again" : "Došlo k chybě („{message}“). Zkuste to znovu", "An error occurred. Please try again" : "Došlo k chybě. Zkuste to znovu", - "{sharee} (group)" : "{sharee} (skupina)", - "{sharee} (remote)" : "{sharee} (na protějšku)", "{sharee} (remote group)" : "{sharee} (skupina na protějšku)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (konverzace)", "Share" : "Sdílet", "Name or email address..." : "Jméno nebo e-mailová adresa…", "Name or federated cloud ID..." : "Jméno nebo identifikátor v rámci sdruženého cloudu…", @@ -356,6 +350,7 @@ OC.L10N.register( "For help, see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation</a>." : "Pro pomoc, nahlédněte do <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">dokumentace</a>.", "I know that if I continue doing the update via web UI has the risk, that the request runs into a timeout and could cause data loss, but I have a backup and know how to restore my instance in case of a failure." : "Beru na vědomí, že při aktualizaci skrze webové rozhraní hrozí nebezpečí vypršení požadavku, který může vyústit ve ztrátu dat. Mám pro takový případ zálohu a vím, jak ji v případě selhání obnovit.", "Upgrade via web on my own risk" : "Na vlastní nebezpečí aktualizovat skrze web", + "Maintenance mode" : "Režim údržby", "This %s instance is currently in maintenance mode, which may take a while." : "Tato instalace %s je právě ve stavu údržby a ta může chvíli trvat.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Pokud se tato zpráva objevuje opakovaně nebo nečekaně, obraťte se správce systému.", "Updated \"%s\" to %s" : "Aktualizováno z „%s“ na %s", @@ -380,6 +375,9 @@ OC.L10N.register( "Error setting expiration date" : "Chyba při nastavení data skončení platnosti", "The public link will expire no later than {days} days after it is created" : "Veřejný odkaz vyprší nejpozději {days} dní od svého vytvoření", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} sdílí pomocí odkazu", + "{sharee} (group)" : "{sharee} (skupina)", + "{sharee} (remote)" : "{sharee} (na protějšku)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Sdílejte s dalšími lidmi zadáním uživatelského jména, skupiny, federovaného cloud ID, nebo e-mailové adresy.", "Share with other people by entering a user or group or a federated cloud ID." : "Sdílejte s dalšími lidmi zadáním uživatelského jména, skupiny, nebo sdruženého cloud ID.", "Share with other people by entering a user or group or an email address." : "Sdílejte s dalšími lidmi zadáním uživatelského jména, jména skupiny, nebo e-mailové adresy.", @@ -411,6 +409,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Chystáte se povolit %s přístup k vašemu %s účtu.", "Depending on your configuration, this button could also work to trust the domain:" : "V závislosti na vaší konfiguraci by pro označení domény za důvěryhodnou mohlo fungovat i toto tlačítko:", "Copy URL" : "Kopírovat URL", + "Enable" : "Povolit", + "{sharee} (conversation)" : "{sharee} (konverzace)", "Please log in before granting %s access to your %s account." : "Přihlaste se před udělením %s přístupu k vašemu %s účtu.", "Further information how to configure this can be found in the %sdocumentation%s." : "Více informací o tom, jak toto nastavit, jsou k dispozici v%sdokumentaci%s." }, diff --git a/core/l10n/cs.json b/core/l10n/cs.json index 4a01f68d6da..b484ec296a8 100644 --- a/core/l10n/cs.json +++ b/core/l10n/cs.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Zapnut režim údržby", "Turned off maintenance mode" : "Vypnut režim údržby", "Maintenance mode is kept active" : "Režim údržby je aktivní", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Čekání na dokončení cronu (zkontroluje znovu za 5 sekund)…", "Updating database schema" : "Aktualizace schéma databáze", "Updated database" : "Zaktualizována databáze", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Probíhá ověření, zda je možné aktualizovat schéma databáze (toto může trvat déle v závislosti na velikosti databáze)", @@ -158,12 +157,12 @@ "Choose a password for the public link" : "Zadej heslo pro tento veřejný odkaz", "Choose a password for the public link or press the \"Enter\" key" : "Zvolte heslo pro veřejný odkaz nebo stiskněte klávesu „Enter“", "Copied!" : "Zkopírováno!", + "Copy link" : "Zkopírovat odkaz", "Not supported!" : "Nepodporováno!", "Press ⌘-C to copy." : "Zmáčknout ⌘-C pro kopírování.", "Press Ctrl-C to copy." : "Zmáčknout Ctrl-C pro kopírování.", "Resharing is not allowed" : "Sdílení už sdílené položky není povoleno", "Share to {name}" : "Sdílet {name}", - "Copy link" : "Zkopírovat odkaz", "Link" : "Odkaz", "Password protect" : "Chránit heslem", "Allow editing" : "Umožnit úpravy", @@ -176,8 +175,10 @@ "Expiration" : "Konec platnosti", "Expiration date" : "Datum skončení platnosti", "Note to recipient" : "Poznámka pro příjemce", + "Unshare" : "Zrušit sdílení", "Share link" : "Odkaz pro sdílení", - "Enable" : "Povolit", + "Password protect by Talk" : "Ochrana heslem pomocí Talk", + "Could not unshare" : "Nelze zrušit sdílení", "Shared with you and the group {group} by {owner}" : "S Vámi a skupinou {group} sdílí {owner}", "Shared with you and {circle} by {owner}" : "Sdíleno s vámi a {circle} od {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Sdíleno {owner} s vámi a konverzací {conversation}", @@ -190,16 +191,13 @@ "email" : "e-mail", "conversation" : "konverzace", "shared by {sharer}" : "Sdílel {sharer}", - "Unshare" : "Zrušit sdílení", "Can reshare" : "Může znovu sdílet", "Can edit" : "Může upravovat", "Can create" : "Může vytvářet", "Can change" : "Může měnit", "Can delete" : "Může mazat", - "Password protect by Talk" : "Ochrana heslem pomocí Talk", "Access control" : "Řízení přístupu", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} nasdílel(a) prostřednictvím odkazu", - "Could not unshare" : "Nelze zrušit sdílení", "Error while sharing" : "Chyba při sdílení", "Share details could not be loaded for this item." : "Detaily sdílení pro tuto položku nelze načíst.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Alespoň {count} znak je vyžadován pro automatické doplňování","Alespoň {count} znaky jsou vyžadovány pro automatické doplňování","Alespoň {count} znaků je vyžadováno pro automatické doplňování","Alespoň {count} znaků je vyžadováno pro automatické doplňování"], @@ -208,12 +206,8 @@ "No users found for {search}" : "Nebyli nalezeni žádní uživatelé pro {search}", "An error occurred (\"{message}\"). Please try again" : "Došlo k chybě („{message}“). Zkuste to znovu", "An error occurred. Please try again" : "Došlo k chybě. Zkuste to znovu", - "{sharee} (group)" : "{sharee} (skupina)", - "{sharee} (remote)" : "{sharee} (na protějšku)", "{sharee} (remote group)" : "{sharee} (skupina na protějšku)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (konverzace)", "Share" : "Sdílet", "Name or email address..." : "Jméno nebo e-mailová adresa…", "Name or federated cloud ID..." : "Jméno nebo identifikátor v rámci sdruženého cloudu…", @@ -354,6 +348,7 @@ "For help, see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation</a>." : "Pro pomoc, nahlédněte do <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">dokumentace</a>.", "I know that if I continue doing the update via web UI has the risk, that the request runs into a timeout and could cause data loss, but I have a backup and know how to restore my instance in case of a failure." : "Beru na vědomí, že při aktualizaci skrze webové rozhraní hrozí nebezpečí vypršení požadavku, který může vyústit ve ztrátu dat. Mám pro takový případ zálohu a vím, jak ji v případě selhání obnovit.", "Upgrade via web on my own risk" : "Na vlastní nebezpečí aktualizovat skrze web", + "Maintenance mode" : "Režim údržby", "This %s instance is currently in maintenance mode, which may take a while." : "Tato instalace %s je právě ve stavu údržby a ta může chvíli trvat.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Pokud se tato zpráva objevuje opakovaně nebo nečekaně, obraťte se správce systému.", "Updated \"%s\" to %s" : "Aktualizováno z „%s“ na %s", @@ -378,6 +373,9 @@ "Error setting expiration date" : "Chyba při nastavení data skončení platnosti", "The public link will expire no later than {days} days after it is created" : "Veřejný odkaz vyprší nejpozději {days} dní od svého vytvoření", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} sdílí pomocí odkazu", + "{sharee} (group)" : "{sharee} (skupina)", + "{sharee} (remote)" : "{sharee} (na protějšku)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Sdílejte s dalšími lidmi zadáním uživatelského jména, skupiny, federovaného cloud ID, nebo e-mailové adresy.", "Share with other people by entering a user or group or a federated cloud ID." : "Sdílejte s dalšími lidmi zadáním uživatelského jména, skupiny, nebo sdruženého cloud ID.", "Share with other people by entering a user or group or an email address." : "Sdílejte s dalšími lidmi zadáním uživatelského jména, jména skupiny, nebo e-mailové adresy.", @@ -409,6 +407,8 @@ "You are about to grant %s access to your %s account." : "Chystáte se povolit %s přístup k vašemu %s účtu.", "Depending on your configuration, this button could also work to trust the domain:" : "V závislosti na vaší konfiguraci by pro označení domény za důvěryhodnou mohlo fungovat i toto tlačítko:", "Copy URL" : "Kopírovat URL", + "Enable" : "Povolit", + "{sharee} (conversation)" : "{sharee} (konverzace)", "Please log in before granting %s access to your %s account." : "Přihlaste se před udělením %s přístupu k vašemu %s účtu.", "Further information how to configure this can be found in the %sdocumentation%s." : "Více informací o tom, jak toto nastavit, jsou k dispozici v%sdokumentaci%s." },"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;" diff --git a/core/l10n/da.js b/core/l10n/da.js index cd0114ff748..eef9c2caa01 100644 --- a/core/l10n/da.js +++ b/core/l10n/da.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Vælg udløbsdato", "Expiration" : "Udløb", "Expiration date" : "Udløbsdato", + "Unshare" : "Fjern deling", "Share link" : "Del link", + "Could not unshare" : "Kunne ikke ophæve deling", "Shared with you and the group {group} by {owner}" : "Delt med dig og gruppen {group} af {owner}", "Shared with you by {owner}" : "Delt med dig af {owner}", "Choose a password for the mail share" : "Vælg et kodeord til mail deling", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "ekstern", "email" : "e-mail", "shared by {sharer}" : "delt af {sharer}", - "Unshare" : "Fjern deling", "Can reshare" : "Kan dele", "Can edit" : "Kan redigere", "Can create" : "Kan oprette", "Can change" : "Kan ændre", "Can delete" : "Kan slette", "Access control" : "Adgangskontrol", - "Could not unshare" : "Kunne ikke ophæve deling", "Error while sharing" : "Fejl under deling", "Share details could not be loaded for this item." : "Detaljer for deling kunne ikke indlæses for dette element.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Mindst {count} tegn er nødvendigt for at benytte autocompletion","Mindst {count} tegn er nødvendige for at benytte autocompletion"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "Ingen brugere fundet for {search}", "An error occurred (\"{message}\"). Please try again" : "Der opstor den fejl (\"{message}\"). Prøv igen", "An error occurred. Please try again" : "Der opstor den fejl. Prøv igen", - "{sharee} (group)" : "{sharee} (gruppe)", - "{sharee} (remote)" : "{sharee} (ekstern)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{share} ({type}, {owner})", "Share" : "Del", "Name or email address..." : "Navn eller e-mail adresse...", @@ -319,6 +316,9 @@ OC.L10N.register( "Error setting expiration date" : "Fejl under sætning af udløbsdato", "The public link will expire no later than {days} days after it is created" : "Det offentlige link udløber senest {days} dage efter det blev oprettet", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delt via link", + "{sharee} (group)" : "{sharee} (gruppe)", + "{sharee} (remote)" : "{sharee} (ekstern)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Del med andre ved at indtaste et brugernavn, en gruppe, et federated cloud id eller en e-mail adresse.", "Share with other people by entering a user or group or a federated cloud ID." : "Del med andre ved at indtaste et brugernavn, en gruppe eller et federated cloud id.", "Share with other people by entering a user or group or an email address." : "Del med andre ved at indtaste et brugernavn, en gruppe eller e-mail adresse.", diff --git a/core/l10n/da.json b/core/l10n/da.json index 26938bb5a20..24fcf29594f 100644 --- a/core/l10n/da.json +++ b/core/l10n/da.json @@ -144,7 +144,9 @@ "Set expiration date" : "Vælg udløbsdato", "Expiration" : "Udløb", "Expiration date" : "Udløbsdato", + "Unshare" : "Fjern deling", "Share link" : "Del link", + "Could not unshare" : "Kunne ikke ophæve deling", "Shared with you and the group {group} by {owner}" : "Delt med dig og gruppen {group} af {owner}", "Shared with you by {owner}" : "Delt med dig af {owner}", "Choose a password for the mail share" : "Vælg et kodeord til mail deling", @@ -152,14 +154,12 @@ "remote" : "ekstern", "email" : "e-mail", "shared by {sharer}" : "delt af {sharer}", - "Unshare" : "Fjern deling", "Can reshare" : "Kan dele", "Can edit" : "Kan redigere", "Can create" : "Kan oprette", "Can change" : "Kan ændre", "Can delete" : "Kan slette", "Access control" : "Adgangskontrol", - "Could not unshare" : "Kunne ikke ophæve deling", "Error while sharing" : "Fejl under deling", "Share details could not be loaded for this item." : "Detaljer for deling kunne ikke indlæses for dette element.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Mindst {count} tegn er nødvendigt for at benytte autocompletion","Mindst {count} tegn er nødvendige for at benytte autocompletion"], @@ -168,9 +168,6 @@ "No users found for {search}" : "Ingen brugere fundet for {search}", "An error occurred (\"{message}\"). Please try again" : "Der opstor den fejl (\"{message}\"). Prøv igen", "An error occurred. Please try again" : "Der opstor den fejl. Prøv igen", - "{sharee} (group)" : "{sharee} (gruppe)", - "{sharee} (remote)" : "{sharee} (ekstern)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{share} ({type}, {owner})", "Share" : "Del", "Name or email address..." : "Navn eller e-mail adresse...", @@ -317,6 +314,9 @@ "Error setting expiration date" : "Fejl under sætning af udløbsdato", "The public link will expire no later than {days} days after it is created" : "Det offentlige link udløber senest {days} dage efter det blev oprettet", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delt via link", + "{sharee} (group)" : "{sharee} (gruppe)", + "{sharee} (remote)" : "{sharee} (ekstern)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Del med andre ved at indtaste et brugernavn, en gruppe, et federated cloud id eller en e-mail adresse.", "Share with other people by entering a user or group or a federated cloud ID." : "Del med andre ved at indtaste et brugernavn, en gruppe eller et federated cloud id.", "Share with other people by entering a user or group or an email address." : "Del med andre ved at indtaste et brugernavn, en gruppe eller e-mail adresse.", diff --git a/core/l10n/de.js b/core/l10n/de.js index 260bb9ef824..72086892685 100644 --- a/core/l10n/de.js +++ b/core/l10n/de.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Wartungsmodus eingeschaltet", "Turned off maintenance mode" : "Wartungsmodus ausgeschaltet", "Maintenance mode is kept active" : "Wartungsmodus bleibt aktiviert", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Warte auf das Beenden von Cron (neue Prüfung in 5 Sekunden)…", "Updating database schema" : "Das Datenbankschema wird aktualisiert", "Updated database" : "Datenbank aktualisiert", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Prüft, ob das Datenbankschema aktualisiert werden kann (dies kann je nach Datenbankgröße sehr lange dauern)", @@ -160,13 +159,17 @@ OC.L10N.register( "Choose a password for the public link" : "Wähle ein Passwort für den öffentlichen Link", "Choose a password for the public link or press the \"Enter\" key" : "Wähle ein Passwort für die öffentliche Freigabe oder drücke \"Eingabe\"", "Copied!" : "Kopiert!", + "Copy link" : "Link kopieren", "Not supported!" : "Nicht unterstützt!", "Press ⌘-C to copy." : "Zum Kopieren ⌘-C drücken.", "Press Ctrl-C to copy." : "Zum Kopieren Strg-C drücken.", + "Unable to create a link share" : "Öffentlicher Link kann nicht erstellt werden", + "Unable to toggle this option" : "Option kann nicht umgeschaltet werden", "Resharing is not allowed" : "Das Weiterverteilen ist nicht erlaubt", "Share to {name}" : "Mit {name} teilen", - "Copy link" : "Link kopieren", "Link" : "Link", + "Hide download" : "Download verbergen", + "Password protection enforced" : "Passwortschutz erzwungen", "Password protect" : "Passwortschutz", "Allow editing" : "Bearbeitung erlauben", "Email link to person" : "Link per E-Mail verschicken", @@ -174,12 +177,19 @@ OC.L10N.register( "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Read only" : "Schreibgeschützt", "File drop (upload only)" : "Dateien ablegen (nur Hochladen)", + "Expiration date enforced" : "Ablaufdatum erzwungen", "Set expiration date" : "Setze ein Ablaufdatum", "Expiration" : "Ablaufdatum", "Expiration date" : "Ablaufdatum", "Note to recipient" : "Notiz an Empfänger", + "Unshare" : "Freigabe aufheben", + "Delete share link" : "Freigabe-Link löschen", + "Add another link" : "Weiteren Link hinzufügen", + "Password protection for links is mandatory" : "Passwortschutz für Links ist obligatorisch", "Share link" : "Link teilen", - "Enable" : "Aktivieren", + "New share link" : "Neuer Freigabelink", + "Password protect by Talk" : "Passwortgeschützt von Talk", + "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Shared with you and the group {group} by {owner}" : "{owner} hat dies mit Dir und der Gruppe {group} geteilt", "Shared with you and {circle} by {owner}" : "Von {owner} mit Dir und {circle} geteilt", "Shared with you and the conversation {conversation} by {owner}" : "Von {owner} mit Ihnen und der Unterhaltung {conversation} geteilt", @@ -192,16 +202,13 @@ OC.L10N.register( "email" : "E-Mail", "conversation" : "Unterhaltung", "shared by {sharer}" : "Geteilt von {sharer}", - "Unshare" : "Freigabe aufheben", "Can reshare" : "kann weiterteilen", "Can edit" : "kann bearbeiten", "Can create" : "kann erstellen", "Can change" : "kann ändern", "Can delete" : "kann löschen", - "Password protect by Talk" : "Passwortgeschützt von Talk", "Access control" : "Zugriffskontrolle", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} mittels Link geteilt", - "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Error while sharing" : "Fehler beim Teilen", "Share details could not be loaded for this item." : "Details der geteilten Freigabe zu diesem Eintrag konnten nicht geladen werden.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Mindestens {count} Zeichen wird für die Autovervollständigung benötigt","Mindestens {count} Zeichen werden für die Autovervollständigung benötigt"], @@ -210,12 +217,10 @@ OC.L10N.register( "No users found for {search}" : "Keine Benutzer für {search} gefunden", "An error occurred (\"{message}\"). Please try again" : "Benötigt keine Übersetzung. Für iOS wird nur die formelle Übersetzung verwendet (de_DE). ", "An error occurred. Please try again" : "Es ist ein Fehler aufgetreten. Bitte versuche es noch einmal", - "{sharee} (group)" : "{sharee} (Gruppe)", - "{sharee} (remote)" : "{sharee} (remote)", "{sharee} (remote group)" : "{sharee} (externe Gruppe)", - "{sharee} (email)" : "{sharee} (E-Mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Start", + "Other" : "Andere", "Share" : "Teilen", "Name or email address..." : "Name oder E-Mail-Adresse…", "Name or federated cloud ID..." : "Name oder Federated-Cloud-ID…", @@ -301,6 +306,7 @@ OC.L10N.register( "Skip to main content" : "Zum Hauptinhalt springen", "Skip to navigation of app" : "Zum Navigationsbereich der App springen", "More apps" : "Weitere Apps", + "More" : "Mehr", "More apps menu" : "Weitere Apps-Menü", "Search" : "Suche", "Reset search" : "Suche zurücksetzen", @@ -382,6 +388,9 @@ OC.L10N.register( "Error setting expiration date" : "Fehler beim Setzen des Ablaufdatums", "The public link will expire no later than {days} days after it is created" : "Der öffentliche Link wird spätestens {days} Tage nach seiner Erstellung ablaufen", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt", + "{sharee} (group)" : "{sharee} (Gruppe)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (E-Mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Teile mit Anderen, indem Du einen Benutzer, eine Gruppe, eine Federated-Cloud-ID oder eine E-Mail-Adressen eingibst.", "Share with other people by entering a user or group or a federated cloud ID." : "Teile mit Anderen, indem Du einen Benutzer, eine Gruppe, oder eine Federated-Cloud-ID eingibst.", "Share with other people by entering a user or group or an email address." : "Teile mit Anderen, indem Du einen Benutzer, eine Gruppe, oder eine E-Mail-Adresse eingibst.", @@ -413,6 +422,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Du bist dabei, %s Zugriff auf Dein %s-Konto zu gewähren.", "Depending on your configuration, this button could also work to trust the domain:" : "Abhängig von Deiner Konfiguration kann diese Schaltfläche verwandt werden, um die Domain als vertrauenswürdig einzustufen:", "Copy URL" : "URL kopieren", + "Enable" : "Aktivieren", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Bitte anmelden, bevor Du %s Zugriff auf Dein %s-Konto gewährst.", "Further information how to configure this can be found in the %sdocumentation%s." : "Weitere Informationen zur Konfiguration findest du in der %sDokumentation%s." }, diff --git a/core/l10n/de.json b/core/l10n/de.json index cf5b11bb679..ea9592b1e47 100644 --- a/core/l10n/de.json +++ b/core/l10n/de.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Wartungsmodus eingeschaltet", "Turned off maintenance mode" : "Wartungsmodus ausgeschaltet", "Maintenance mode is kept active" : "Wartungsmodus bleibt aktiviert", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Warte auf das Beenden von Cron (neue Prüfung in 5 Sekunden)…", "Updating database schema" : "Das Datenbankschema wird aktualisiert", "Updated database" : "Datenbank aktualisiert", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Prüft, ob das Datenbankschema aktualisiert werden kann (dies kann je nach Datenbankgröße sehr lange dauern)", @@ -158,13 +157,17 @@ "Choose a password for the public link" : "Wähle ein Passwort für den öffentlichen Link", "Choose a password for the public link or press the \"Enter\" key" : "Wähle ein Passwort für die öffentliche Freigabe oder drücke \"Eingabe\"", "Copied!" : "Kopiert!", + "Copy link" : "Link kopieren", "Not supported!" : "Nicht unterstützt!", "Press ⌘-C to copy." : "Zum Kopieren ⌘-C drücken.", "Press Ctrl-C to copy." : "Zum Kopieren Strg-C drücken.", + "Unable to create a link share" : "Öffentlicher Link kann nicht erstellt werden", + "Unable to toggle this option" : "Option kann nicht umgeschaltet werden", "Resharing is not allowed" : "Das Weiterverteilen ist nicht erlaubt", "Share to {name}" : "Mit {name} teilen", - "Copy link" : "Link kopieren", "Link" : "Link", + "Hide download" : "Download verbergen", + "Password protection enforced" : "Passwortschutz erzwungen", "Password protect" : "Passwortschutz", "Allow editing" : "Bearbeitung erlauben", "Email link to person" : "Link per E-Mail verschicken", @@ -172,12 +175,19 @@ "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Read only" : "Schreibgeschützt", "File drop (upload only)" : "Dateien ablegen (nur Hochladen)", + "Expiration date enforced" : "Ablaufdatum erzwungen", "Set expiration date" : "Setze ein Ablaufdatum", "Expiration" : "Ablaufdatum", "Expiration date" : "Ablaufdatum", "Note to recipient" : "Notiz an Empfänger", + "Unshare" : "Freigabe aufheben", + "Delete share link" : "Freigabe-Link löschen", + "Add another link" : "Weiteren Link hinzufügen", + "Password protection for links is mandatory" : "Passwortschutz für Links ist obligatorisch", "Share link" : "Link teilen", - "Enable" : "Aktivieren", + "New share link" : "Neuer Freigabelink", + "Password protect by Talk" : "Passwortgeschützt von Talk", + "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Shared with you and the group {group} by {owner}" : "{owner} hat dies mit Dir und der Gruppe {group} geteilt", "Shared with you and {circle} by {owner}" : "Von {owner} mit Dir und {circle} geteilt", "Shared with you and the conversation {conversation} by {owner}" : "Von {owner} mit Ihnen und der Unterhaltung {conversation} geteilt", @@ -190,16 +200,13 @@ "email" : "E-Mail", "conversation" : "Unterhaltung", "shared by {sharer}" : "Geteilt von {sharer}", - "Unshare" : "Freigabe aufheben", "Can reshare" : "kann weiterteilen", "Can edit" : "kann bearbeiten", "Can create" : "kann erstellen", "Can change" : "kann ändern", "Can delete" : "kann löschen", - "Password protect by Talk" : "Passwortgeschützt von Talk", "Access control" : "Zugriffskontrolle", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} mittels Link geteilt", - "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Error while sharing" : "Fehler beim Teilen", "Share details could not be loaded for this item." : "Details der geteilten Freigabe zu diesem Eintrag konnten nicht geladen werden.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Mindestens {count} Zeichen wird für die Autovervollständigung benötigt","Mindestens {count} Zeichen werden für die Autovervollständigung benötigt"], @@ -208,12 +215,10 @@ "No users found for {search}" : "Keine Benutzer für {search} gefunden", "An error occurred (\"{message}\"). Please try again" : "Benötigt keine Übersetzung. Für iOS wird nur die formelle Übersetzung verwendet (de_DE). ", "An error occurred. Please try again" : "Es ist ein Fehler aufgetreten. Bitte versuche es noch einmal", - "{sharee} (group)" : "{sharee} (Gruppe)", - "{sharee} (remote)" : "{sharee} (remote)", "{sharee} (remote group)" : "{sharee} (externe Gruppe)", - "{sharee} (email)" : "{sharee} (E-Mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Start", + "Other" : "Andere", "Share" : "Teilen", "Name or email address..." : "Name oder E-Mail-Adresse…", "Name or federated cloud ID..." : "Name oder Federated-Cloud-ID…", @@ -299,6 +304,7 @@ "Skip to main content" : "Zum Hauptinhalt springen", "Skip to navigation of app" : "Zum Navigationsbereich der App springen", "More apps" : "Weitere Apps", + "More" : "Mehr", "More apps menu" : "Weitere Apps-Menü", "Search" : "Suche", "Reset search" : "Suche zurücksetzen", @@ -380,6 +386,9 @@ "Error setting expiration date" : "Fehler beim Setzen des Ablaufdatums", "The public link will expire no later than {days} days after it is created" : "Der öffentliche Link wird spätestens {days} Tage nach seiner Erstellung ablaufen", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt", + "{sharee} (group)" : "{sharee} (Gruppe)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (E-Mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Teile mit Anderen, indem Du einen Benutzer, eine Gruppe, eine Federated-Cloud-ID oder eine E-Mail-Adressen eingibst.", "Share with other people by entering a user or group or a federated cloud ID." : "Teile mit Anderen, indem Du einen Benutzer, eine Gruppe, oder eine Federated-Cloud-ID eingibst.", "Share with other people by entering a user or group or an email address." : "Teile mit Anderen, indem Du einen Benutzer, eine Gruppe, oder eine E-Mail-Adresse eingibst.", @@ -411,6 +420,8 @@ "You are about to grant %s access to your %s account." : "Du bist dabei, %s Zugriff auf Dein %s-Konto zu gewähren.", "Depending on your configuration, this button could also work to trust the domain:" : "Abhängig von Deiner Konfiguration kann diese Schaltfläche verwandt werden, um die Domain als vertrauenswürdig einzustufen:", "Copy URL" : "URL kopieren", + "Enable" : "Aktivieren", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Bitte anmelden, bevor Du %s Zugriff auf Dein %s-Konto gewährst.", "Further information how to configure this can be found in the %sdocumentation%s." : "Weitere Informationen zur Konfiguration findest du in der %sDokumentation%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js index 7a7b1b15739..b96f3d6100c 100644 --- a/core/l10n/de_DE.js +++ b/core/l10n/de_DE.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Wartungsmodus eingeschaltet ", "Turned off maintenance mode" : "Wartungsmodus ausgeschaltet", "Maintenance mode is kept active" : "Wartungsmodus bleibt aktiviert", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Warte auf das Beenden von Cron (neue Prüfung in 5 Sekunden)…", "Updating database schema" : "Das Datenbankschema wird aktualisiert", "Updated database" : "Datenbank aktualisiert", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Prüft, ob das Datenbankschema aktualisiert werden kann (dies kann je nach Datenbankgröße sehr lange dauern)", @@ -160,13 +159,17 @@ OC.L10N.register( "Choose a password for the public link" : "Wählen Sie ein Passwort für den öffentlichen Link", "Choose a password for the public link or press the \"Enter\" key" : "Wählen Sie ein Passwort für die öffentliche Freigabe oder drücken Sie \"Eingabe\"", "Copied!" : "Kopiert!", + "Copy link" : "Link kopieren", "Not supported!" : "Nicht unterstützt!", "Press ⌘-C to copy." : "Zum Kopieren ⌘-C drücken.", "Press Ctrl-C to copy." : "Zum Kopieren Strg-C drücken.", + "Unable to create a link share" : "Öffentlicher Link kann nicht erstellt werden", + "Unable to toggle this option" : "Option kann nicht umgeschaltet werden", "Resharing is not allowed" : "Das Weiterverteilen ist nicht erlaubt", "Share to {name}" : "Mit {name} teilen", - "Copy link" : "Link kopieren", "Link" : "Link", + "Hide download" : "Download verbergen", + "Password protection enforced" : "Passwortschutz erzwungen", "Password protect" : "Passwortschutz", "Allow editing" : "Bearbeitung erlauben", "Email link to person" : "Link per E-Mail verschicken", @@ -174,12 +177,19 @@ OC.L10N.register( "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Read only" : "Schreibgeschützt", "File drop (upload only)" : "Dateien ablegen (nur Hochladen)", + "Expiration date enforced" : "Ablaufdatum erzwungen", "Set expiration date" : "Ein Ablaufdatum setzen", "Expiration" : "Ablauf", "Expiration date" : "Ablaufdatum", "Note to recipient" : "Notiz an Empfänger", + "Unshare" : "Freigabe aufheben", + "Delete share link" : "Freigabe-Link löschen", + "Add another link" : "Weiteren Link hinzufügen", + "Password protection for links is mandatory" : "Passwortschutz für Links ist obligatorisch", "Share link" : "Link teilen", - "Enable" : "Aktivieren", + "New share link" : "Neuer Freigabelink", + "Password protect by Talk" : "Passwortgeschützt von Talk", + "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Shared with you and the group {group} by {owner}" : "Von {owner} mit Ihnen und der Gruppe {group} geteilt.", "Shared with you and {circle} by {owner}" : "Von {owner} mit Ihnen und {circle} geteilt", "Shared with you and the conversation {conversation} by {owner}" : "Von {owner} mit Ihnen und der Unterhaltung {conversation} geteilt", @@ -192,16 +202,13 @@ OC.L10N.register( "email" : "E-Mail", "conversation" : "Unterhaltung", "shared by {sharer}" : "Geteilt von {sharer}", - "Unshare" : "Freigabe aufheben", "Can reshare" : "kann weiterteilen", "Can edit" : "kann bearbeiten", "Can create" : "kann erstellen", "Can change" : "kann ändern", "Can delete" : "kann löschen", - "Password protect by Talk" : "Passwortgeschützt von Talk", "Access control" : "Zugriffskontrolle", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} mittels Link geteilt", - "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Error while sharing" : "Fehler beim Teilen", "Share details could not be loaded for this item." : "Details der geteilten Freigabe zu diesem Eintrag konnten nicht geladen werden.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Mindestens {count} Zeichen wird für die Autovervollständigung benötigt","Mindestens {count} Zeichen werden für die Autovervollständigung benötigt"], @@ -210,12 +217,10 @@ OC.L10N.register( "No users found for {search}" : "Keine Benutzer für {search} gefunden", "An error occurred (\"{message}\"). Please try again" : "Es ist ein Fehler aufgetreten (\"{message}\"). Bitte erneut versuchen.", "An error occurred. Please try again" : "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es noch einmal", - "{sharee} (group)" : "{sharee} (Gruppe)", - "{sharee} (remote)" : "{sharee} (remote)", "{sharee} (remote group)" : "{sharee} (Externe Gruppe)", - "{sharee} (email)" : "{sharee} (E-Mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Start", + "Other" : "Andere", "Share" : "Teilen", "Name or email address..." : "Name oder E-Mail-Adresse…", "Name or federated cloud ID..." : "Name oder Federated-Cloud-ID…", @@ -301,6 +306,7 @@ OC.L10N.register( "Skip to main content" : "Zum Hauptinhalt springen", "Skip to navigation of app" : "Zum Navigationsbereich der App springen", "More apps" : "Weitere Apps", + "More" : "Mehr", "More apps menu" : "Weitere Apps-Menü", "Search" : "Suche", "Reset search" : "Suche zurücksetzen", @@ -382,6 +388,9 @@ OC.L10N.register( "Error setting expiration date" : "Fehler beim Setzen des Ablaufdatums", "The public link will expire no later than {days} days after it is created" : "Der öffentliche Link wird spätestens {days} Tage nach seiner Erstellung ablaufen", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt", + "{sharee} (group)" : "{sharee} (Gruppe)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (E-Mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Teilen mit Anderen, indem Sie einen Benutzer, eine Gruppe, eine Federated-Cloud-ID oder eine E-Mail-Adresse eingeben.", "Share with other people by entering a user or group or a federated cloud ID." : "Teilen mit Anderen, indem Sie einen Benutzer, eine Gruppe, oder eine Federated-Cloud-ID eingeben.", "Share with other people by entering a user or group or an email address." : "Teilen mit Anderen, indem Sie einen Benutzer, eine Gruppe, oder eine E-Mail-Adresse eingeben.", @@ -413,6 +422,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Sie sind dabei, %s Zugriff auf Ihr %s-Konto zu gewähren.", "Depending on your configuration, this button could also work to trust the domain:" : "Abhängig von Ihrer Konfiguration kann diese Schaltfläche verwandt werden, um die Domain als vertrauenswürdig einzustufen:", "Copy URL" : "URL kopieren", + "Enable" : "Aktivieren", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Bitte anmelden, bevor Du %s Zugriff auf Dein %s-Konto gewährst.", "Further information how to configure this can be found in the %sdocumentation%s." : "Weitere Informationen zur Konfiguration finden Sie in der %sDokumentation%s." }, diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json index dc1ed554487..29b14325991 100644 --- a/core/l10n/de_DE.json +++ b/core/l10n/de_DE.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Wartungsmodus eingeschaltet ", "Turned off maintenance mode" : "Wartungsmodus ausgeschaltet", "Maintenance mode is kept active" : "Wartungsmodus bleibt aktiviert", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Warte auf das Beenden von Cron (neue Prüfung in 5 Sekunden)…", "Updating database schema" : "Das Datenbankschema wird aktualisiert", "Updated database" : "Datenbank aktualisiert", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Prüft, ob das Datenbankschema aktualisiert werden kann (dies kann je nach Datenbankgröße sehr lange dauern)", @@ -158,13 +157,17 @@ "Choose a password for the public link" : "Wählen Sie ein Passwort für den öffentlichen Link", "Choose a password for the public link or press the \"Enter\" key" : "Wählen Sie ein Passwort für die öffentliche Freigabe oder drücken Sie \"Eingabe\"", "Copied!" : "Kopiert!", + "Copy link" : "Link kopieren", "Not supported!" : "Nicht unterstützt!", "Press ⌘-C to copy." : "Zum Kopieren ⌘-C drücken.", "Press Ctrl-C to copy." : "Zum Kopieren Strg-C drücken.", + "Unable to create a link share" : "Öffentlicher Link kann nicht erstellt werden", + "Unable to toggle this option" : "Option kann nicht umgeschaltet werden", "Resharing is not allowed" : "Das Weiterverteilen ist nicht erlaubt", "Share to {name}" : "Mit {name} teilen", - "Copy link" : "Link kopieren", "Link" : "Link", + "Hide download" : "Download verbergen", + "Password protection enforced" : "Passwortschutz erzwungen", "Password protect" : "Passwortschutz", "Allow editing" : "Bearbeitung erlauben", "Email link to person" : "Link per E-Mail verschicken", @@ -172,12 +175,19 @@ "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Read only" : "Schreibgeschützt", "File drop (upload only)" : "Dateien ablegen (nur Hochladen)", + "Expiration date enforced" : "Ablaufdatum erzwungen", "Set expiration date" : "Ein Ablaufdatum setzen", "Expiration" : "Ablauf", "Expiration date" : "Ablaufdatum", "Note to recipient" : "Notiz an Empfänger", + "Unshare" : "Freigabe aufheben", + "Delete share link" : "Freigabe-Link löschen", + "Add another link" : "Weiteren Link hinzufügen", + "Password protection for links is mandatory" : "Passwortschutz für Links ist obligatorisch", "Share link" : "Link teilen", - "Enable" : "Aktivieren", + "New share link" : "Neuer Freigabelink", + "Password protect by Talk" : "Passwortgeschützt von Talk", + "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Shared with you and the group {group} by {owner}" : "Von {owner} mit Ihnen und der Gruppe {group} geteilt.", "Shared with you and {circle} by {owner}" : "Von {owner} mit Ihnen und {circle} geteilt", "Shared with you and the conversation {conversation} by {owner}" : "Von {owner} mit Ihnen und der Unterhaltung {conversation} geteilt", @@ -190,16 +200,13 @@ "email" : "E-Mail", "conversation" : "Unterhaltung", "shared by {sharer}" : "Geteilt von {sharer}", - "Unshare" : "Freigabe aufheben", "Can reshare" : "kann weiterteilen", "Can edit" : "kann bearbeiten", "Can create" : "kann erstellen", "Can change" : "kann ändern", "Can delete" : "kann löschen", - "Password protect by Talk" : "Passwortgeschützt von Talk", "Access control" : "Zugriffskontrolle", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} mittels Link geteilt", - "Could not unshare" : "Freigabe konnte nicht aufgehoben werden", "Error while sharing" : "Fehler beim Teilen", "Share details could not be loaded for this item." : "Details der geteilten Freigabe zu diesem Eintrag konnten nicht geladen werden.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Mindestens {count} Zeichen wird für die Autovervollständigung benötigt","Mindestens {count} Zeichen werden für die Autovervollständigung benötigt"], @@ -208,12 +215,10 @@ "No users found for {search}" : "Keine Benutzer für {search} gefunden", "An error occurred (\"{message}\"). Please try again" : "Es ist ein Fehler aufgetreten (\"{message}\"). Bitte erneut versuchen.", "An error occurred. Please try again" : "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es noch einmal", - "{sharee} (group)" : "{sharee} (Gruppe)", - "{sharee} (remote)" : "{sharee} (remote)", "{sharee} (remote group)" : "{sharee} (Externe Gruppe)", - "{sharee} (email)" : "{sharee} (E-Mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Start", + "Other" : "Andere", "Share" : "Teilen", "Name or email address..." : "Name oder E-Mail-Adresse…", "Name or federated cloud ID..." : "Name oder Federated-Cloud-ID…", @@ -299,6 +304,7 @@ "Skip to main content" : "Zum Hauptinhalt springen", "Skip to navigation of app" : "Zum Navigationsbereich der App springen", "More apps" : "Weitere Apps", + "More" : "Mehr", "More apps menu" : "Weitere Apps-Menü", "Search" : "Suche", "Reset search" : "Suche zurücksetzen", @@ -380,6 +386,9 @@ "Error setting expiration date" : "Fehler beim Setzen des Ablaufdatums", "The public link will expire no later than {days} days after it is created" : "Der öffentliche Link wird spätestens {days} Tage nach seiner Erstellung ablaufen", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt", + "{sharee} (group)" : "{sharee} (Gruppe)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (E-Mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Teilen mit Anderen, indem Sie einen Benutzer, eine Gruppe, eine Federated-Cloud-ID oder eine E-Mail-Adresse eingeben.", "Share with other people by entering a user or group or a federated cloud ID." : "Teilen mit Anderen, indem Sie einen Benutzer, eine Gruppe, oder eine Federated-Cloud-ID eingeben.", "Share with other people by entering a user or group or an email address." : "Teilen mit Anderen, indem Sie einen Benutzer, eine Gruppe, oder eine E-Mail-Adresse eingeben.", @@ -411,6 +420,8 @@ "You are about to grant %s access to your %s account." : "Sie sind dabei, %s Zugriff auf Ihr %s-Konto zu gewähren.", "Depending on your configuration, this button could also work to trust the domain:" : "Abhängig von Ihrer Konfiguration kann diese Schaltfläche verwandt werden, um die Domain als vertrauenswürdig einzustufen:", "Copy URL" : "URL kopieren", + "Enable" : "Aktivieren", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Bitte anmelden, bevor Du %s Zugriff auf Dein %s-Konto gewährst.", "Further information how to configure this can be found in the %sdocumentation%s." : "Weitere Informationen zur Konfiguration finden Sie in der %sDokumentation%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/el.js b/core/l10n/el.js index 490cace3f23..1aa379fb154 100644 --- a/core/l10n/el.js +++ b/core/l10n/el.js @@ -132,7 +132,9 @@ OC.L10N.register( "Set expiration date" : "Ορισμός ημερομηνίας λήξης", "Expiration" : "Λήξη", "Expiration date" : "Ημερομηνία λήξης", + "Unshare" : "Αναίρεση διαμοιρασμού", "Share link" : "Διαμοιρασμός συνδέσμου", + "Could not unshare" : "Δεν μπορεί να γίνει αναίρεση διαμοιρασμού", "Shared with you and the group {group} by {owner}" : "Διαμοιράστηκε με σας και με την ομάδα {group} του {owner}", "Shared with you by {owner}" : "Διαμοιράστηκε με σας από τον {owner}", "Choose a password for the mail share" : "Επιλογή συνθηματικού για διαμοιρασμό με αλληλογραφία", @@ -140,14 +142,12 @@ OC.L10N.register( "remote" : "απομακρυσμένα", "email" : "ηλεκτρονικό ταχυδρομείο", "shared by {sharer}" : "διαμοιράστηκε από {sharer}", - "Unshare" : "Αναίρεση διαμοιρασμού", "Can reshare" : "Δυνατότητα να διαμοιραστεί ξανά", "Can edit" : "Δυνατότητα επεξεργασίας", "Can create" : "Δυνατότητα δημιουργίας", "Can change" : "Δυνατότητα αλλαγής", "Can delete" : "Δυνατότητα διαγραφής", "Access control" : "Έλεγχος πρόσβασης", - "Could not unshare" : "Δεν μπορεί να γίνει αναίρεση διαμοιρασμού", "Error while sharing" : "Σφάλμα κατά τον διαμοιρασμό", "Share details could not be loaded for this item." : "Αδυναμία φόρτωσης λεπτομερειών διαμοιρασμού για αυτό το αντικείμενο.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Απαιτείται τουλάχιστο {count} χαρακτήρας για αυτόματη συμπλήρωση","Απαιτούνται τουλάχιστο {count} χαρακτήρες για αυτόματη συμπλήρωση"], @@ -155,9 +155,6 @@ OC.L10N.register( "No users or groups found for {search}" : "Δεν βρέθηκαν χρήστες ή ομάδες για την αναζήτηση {search}", "No users found for {search}" : "Δεν βρέθηκαν χρήστες για την αναζήτηση {search}", "An error occurred. Please try again" : "Παρουσιάστηκε σφάλμα. Παρακαλώ δοκιμάστε αργότερα", - "{sharee} (group)" : "{sharee} (ομάδα)", - "{sharee} (remote)" : "{sharee} (απομακρυσμένα)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Διαμοιρασμός", "Name or email address..." : "Όνομα ή διεύθυνση ηλεκτρονικού ταχυδρομείου...", @@ -281,6 +278,9 @@ OC.L10N.register( "Error setting expiration date" : "Σφάλμα κατά τον ορισμό ημερομηνίας λήξης", "The public link will expire no later than {days} days after it is created" : "Ο δημόσιος σύνδεσμος θα απενεργοποιηθεί το πολύ σε {days} ημέρες μετά την δημιουργία του", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} διαμοιράστηκε με σύνδεσμο", + "{sharee} (group)" : "{sharee} (ομάδα)", + "{sharee} (remote)" : "{sharee} (απομακρυσμένα)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Διαμοιραστείτε με άλλους εισάγοντας τον χρήστη ή την ομάδα, το ID του federated cloud ή μια διεύθυνση ηλεκτρονικού ταχυδρομείου.", "Share with other people by entering a user or group or a federated cloud ID." : "Διαμοιραστείτε με άλλους εισάγοντας τον χρήστη ή την ομάδα ή το ID του federated cloud.", "Share with other people by entering a user or group or an email address." : "Διαμοιραστείτε με άλλους εισάγοντας τον χρήστη ή την ομάδα ή μια διεύθυνση ηλεκτρονικού ταχυδρομείου.", diff --git a/core/l10n/el.json b/core/l10n/el.json index e70fff20a1e..56de37a709b 100644 --- a/core/l10n/el.json +++ b/core/l10n/el.json @@ -130,7 +130,9 @@ "Set expiration date" : "Ορισμός ημερομηνίας λήξης", "Expiration" : "Λήξη", "Expiration date" : "Ημερομηνία λήξης", + "Unshare" : "Αναίρεση διαμοιρασμού", "Share link" : "Διαμοιρασμός συνδέσμου", + "Could not unshare" : "Δεν μπορεί να γίνει αναίρεση διαμοιρασμού", "Shared with you and the group {group} by {owner}" : "Διαμοιράστηκε με σας και με την ομάδα {group} του {owner}", "Shared with you by {owner}" : "Διαμοιράστηκε με σας από τον {owner}", "Choose a password for the mail share" : "Επιλογή συνθηματικού για διαμοιρασμό με αλληλογραφία", @@ -138,14 +140,12 @@ "remote" : "απομακρυσμένα", "email" : "ηλεκτρονικό ταχυδρομείο", "shared by {sharer}" : "διαμοιράστηκε από {sharer}", - "Unshare" : "Αναίρεση διαμοιρασμού", "Can reshare" : "Δυνατότητα να διαμοιραστεί ξανά", "Can edit" : "Δυνατότητα επεξεργασίας", "Can create" : "Δυνατότητα δημιουργίας", "Can change" : "Δυνατότητα αλλαγής", "Can delete" : "Δυνατότητα διαγραφής", "Access control" : "Έλεγχος πρόσβασης", - "Could not unshare" : "Δεν μπορεί να γίνει αναίρεση διαμοιρασμού", "Error while sharing" : "Σφάλμα κατά τον διαμοιρασμό", "Share details could not be loaded for this item." : "Αδυναμία φόρτωσης λεπτομερειών διαμοιρασμού για αυτό το αντικείμενο.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Απαιτείται τουλάχιστο {count} χαρακτήρας για αυτόματη συμπλήρωση","Απαιτούνται τουλάχιστο {count} χαρακτήρες για αυτόματη συμπλήρωση"], @@ -153,9 +153,6 @@ "No users or groups found for {search}" : "Δεν βρέθηκαν χρήστες ή ομάδες για την αναζήτηση {search}", "No users found for {search}" : "Δεν βρέθηκαν χρήστες για την αναζήτηση {search}", "An error occurred. Please try again" : "Παρουσιάστηκε σφάλμα. Παρακαλώ δοκιμάστε αργότερα", - "{sharee} (group)" : "{sharee} (ομάδα)", - "{sharee} (remote)" : "{sharee} (απομακρυσμένα)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Διαμοιρασμός", "Name or email address..." : "Όνομα ή διεύθυνση ηλεκτρονικού ταχυδρομείου...", @@ -279,6 +276,9 @@ "Error setting expiration date" : "Σφάλμα κατά τον ορισμό ημερομηνίας λήξης", "The public link will expire no later than {days} days after it is created" : "Ο δημόσιος σύνδεσμος θα απενεργοποιηθεί το πολύ σε {days} ημέρες μετά την δημιουργία του", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} διαμοιράστηκε με σύνδεσμο", + "{sharee} (group)" : "{sharee} (ομάδα)", + "{sharee} (remote)" : "{sharee} (απομακρυσμένα)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Διαμοιραστείτε με άλλους εισάγοντας τον χρήστη ή την ομάδα, το ID του federated cloud ή μια διεύθυνση ηλεκτρονικού ταχυδρομείου.", "Share with other people by entering a user or group or a federated cloud ID." : "Διαμοιραστείτε με άλλους εισάγοντας τον χρήστη ή την ομάδα ή το ID του federated cloud.", "Share with other people by entering a user or group or an email address." : "Διαμοιραστείτε με άλλους εισάγοντας τον χρήστη ή την ομάδα ή μια διεύθυνση ηλεκτρονικού ταχυδρομείου.", diff --git a/core/l10n/en_GB.js b/core/l10n/en_GB.js index 269026c479a..9219cb4c623 100644 --- a/core/l10n/en_GB.js +++ b/core/l10n/en_GB.js @@ -148,7 +148,9 @@ OC.L10N.register( "Set expiration date" : "Set expiration date", "Expiration" : "Expiration", "Expiration date" : "Expiration date", + "Unshare" : "Unshare", "Share link" : "Share link", + "Could not unshare" : "Could not unshare", "Shared with you and the group {group} by {owner}" : "Shared with you and the group {group} by {owner}", "Shared with you by {owner}" : "Shared with you by {owner}", "Choose a password for the mail share" : "Choose a password for the mail share", @@ -156,14 +158,12 @@ OC.L10N.register( "remote" : "remote", "email" : "email", "shared by {sharer}" : "shared by {sharer}", - "Unshare" : "Unshare", "Can reshare" : "Can reshare", "Can edit" : "Can edit", "Can create" : "Can create", "Can change" : "Can change", "Can delete" : "Can delete", "Access control" : "Access control", - "Could not unshare" : "Could not unshare", "Error while sharing" : "Error whilst sharing", "Share details could not be loaded for this item." : "Share details could not be loaded for this item.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["At least {count} character is needed for autocompletion","At least {count} characters are needed for autocompletion"], @@ -172,9 +172,6 @@ OC.L10N.register( "No users found for {search}" : "No users found for {search}", "An error occurred (\"{message}\"). Please try again" : "An error occurred (\"{message}\"). Please try again", "An error occurred. Please try again" : "An error occurred. Please try again", - "{sharee} (group)" : "{sharee} (group)", - "{sharee} (remote)" : "{sharee} (remote)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Share", "Name or email address..." : "Name or email address...", @@ -325,6 +322,9 @@ OC.L10N.register( "Error setting expiration date" : "Error setting expiration date", "The public link will expire no later than {days} days after it is created" : "The public link will expire no later than {days} days after it is created", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} shared via link", + "{sharee} (group)" : "{sharee} (group)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Share with other people by entering a user or group, a federated cloud ID or an email address.", "Share with other people by entering a user or group or a federated cloud ID." : "Share with other people by entering a user or group or a federated cloud ID.", "Share with other people by entering a user or group or an email address." : "Share with other people by entering a user or group or an email address.", diff --git a/core/l10n/en_GB.json b/core/l10n/en_GB.json index 66c984ba1d7..9d87f758795 100644 --- a/core/l10n/en_GB.json +++ b/core/l10n/en_GB.json @@ -146,7 +146,9 @@ "Set expiration date" : "Set expiration date", "Expiration" : "Expiration", "Expiration date" : "Expiration date", + "Unshare" : "Unshare", "Share link" : "Share link", + "Could not unshare" : "Could not unshare", "Shared with you and the group {group} by {owner}" : "Shared with you and the group {group} by {owner}", "Shared with you by {owner}" : "Shared with you by {owner}", "Choose a password for the mail share" : "Choose a password for the mail share", @@ -154,14 +156,12 @@ "remote" : "remote", "email" : "email", "shared by {sharer}" : "shared by {sharer}", - "Unshare" : "Unshare", "Can reshare" : "Can reshare", "Can edit" : "Can edit", "Can create" : "Can create", "Can change" : "Can change", "Can delete" : "Can delete", "Access control" : "Access control", - "Could not unshare" : "Could not unshare", "Error while sharing" : "Error whilst sharing", "Share details could not be loaded for this item." : "Share details could not be loaded for this item.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["At least {count} character is needed for autocompletion","At least {count} characters are needed for autocompletion"], @@ -170,9 +170,6 @@ "No users found for {search}" : "No users found for {search}", "An error occurred (\"{message}\"). Please try again" : "An error occurred (\"{message}\"). Please try again", "An error occurred. Please try again" : "An error occurred. Please try again", - "{sharee} (group)" : "{sharee} (group)", - "{sharee} (remote)" : "{sharee} (remote)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Share", "Name or email address..." : "Name or email address...", @@ -323,6 +320,9 @@ "Error setting expiration date" : "Error setting expiration date", "The public link will expire no later than {days} days after it is created" : "The public link will expire no later than {days} days after it is created", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} shared via link", + "{sharee} (group)" : "{sharee} (group)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Share with other people by entering a user or group, a federated cloud ID or an email address.", "Share with other people by entering a user or group or a federated cloud ID." : "Share with other people by entering a user or group or a federated cloud ID.", "Share with other people by entering a user or group or an email address." : "Share with other people by entering a user or group or an email address.", diff --git a/core/l10n/eo.js b/core/l10n/eo.js index 3900daa108b..8dceb701474 100644 --- a/core/l10n/eo.js +++ b/core/l10n/eo.js @@ -96,29 +96,26 @@ OC.L10N.register( "Set expiration date" : "Agordi limdaton", "Expiration" : "Eksvalidiĝo", "Expiration date" : "Limdato", + "Unshare" : "Malkunhavigi", "Share link" : "Kunhavigi ligilon", + "Could not unshare" : "Ne malkunhaveblas", "Shared with you and the group {group} by {owner}" : "Kunhavigita kun vi kaj la grupo {group} de {owner}", "Shared with you by {owner}" : "Kunhavigita kun vi de {owner}", "group" : "grupo", "remote" : "fora", "email" : "retpoŝto", "shared by {sharer}" : "kunhavigis de {sharer}", - "Unshare" : "Malkunhavigi", "Can reshare" : "Eblas rekunhavigi", "Can edit" : "Povas redakti", "Can create" : "Povas krei", "Can change" : "Eblas ŝanĝi", "Can delete" : "Povas forigi", "Access control" : "Alirkontrolo", - "Could not unshare" : "Ne malkunhaveblas", "Error while sharing" : "Eraro dum kunhavigo", "Share details could not be loaded for this item." : "Kunhavaj detaloj ne ŝargeblis por ĉi tiu ero.", "No users or groups found for {search}" : "Neniu uzanto aŭ grupo troviĝis por {search}", "An error occurred (\"{message}\"). Please try again" : "Eraro okazis (\"{message}\"). Bonvolu provi ree.", "An error occurred. Please try again" : "Eraro okazis. Bonvolu provi ree", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (fora)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Kunhavigi", "Name or email address..." : "Nomo aŭ retpoŝtadreso...", @@ -215,6 +212,9 @@ OC.L10N.register( "Shared with {recipients}" : "Kunhavigis kun {recipients}", "Error setting expiration date" : "Eraro dum agordado de limdato", "The public link will expire no later than {days} days after it is created" : "La publika ligilo senvalidiĝos ne pli malfrue ol {days} tagojn post ĝi kreiĝos", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (fora)", + "{sharee} (email)" : "{sharee} (email)", "This action requires you to confirm your password:" : "Tiu ĉi ago bezonas ke vi konfirmas vian pasvorton:", "Wrong password. Reset it?" : "Falsa pasvorto. Ĉu vi volas rekomenci ĝin?", "Stay logged in" : "Daŭri ensalutinta", diff --git a/core/l10n/eo.json b/core/l10n/eo.json index c48216f51b5..4363db686d5 100644 --- a/core/l10n/eo.json +++ b/core/l10n/eo.json @@ -94,29 +94,26 @@ "Set expiration date" : "Agordi limdaton", "Expiration" : "Eksvalidiĝo", "Expiration date" : "Limdato", + "Unshare" : "Malkunhavigi", "Share link" : "Kunhavigi ligilon", + "Could not unshare" : "Ne malkunhaveblas", "Shared with you and the group {group} by {owner}" : "Kunhavigita kun vi kaj la grupo {group} de {owner}", "Shared with you by {owner}" : "Kunhavigita kun vi de {owner}", "group" : "grupo", "remote" : "fora", "email" : "retpoŝto", "shared by {sharer}" : "kunhavigis de {sharer}", - "Unshare" : "Malkunhavigi", "Can reshare" : "Eblas rekunhavigi", "Can edit" : "Povas redakti", "Can create" : "Povas krei", "Can change" : "Eblas ŝanĝi", "Can delete" : "Povas forigi", "Access control" : "Alirkontrolo", - "Could not unshare" : "Ne malkunhaveblas", "Error while sharing" : "Eraro dum kunhavigo", "Share details could not be loaded for this item." : "Kunhavaj detaloj ne ŝargeblis por ĉi tiu ero.", "No users or groups found for {search}" : "Neniu uzanto aŭ grupo troviĝis por {search}", "An error occurred (\"{message}\"). Please try again" : "Eraro okazis (\"{message}\"). Bonvolu provi ree.", "An error occurred. Please try again" : "Eraro okazis. Bonvolu provi ree", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (fora)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Kunhavigi", "Name or email address..." : "Nomo aŭ retpoŝtadreso...", @@ -213,6 +210,9 @@ "Shared with {recipients}" : "Kunhavigis kun {recipients}", "Error setting expiration date" : "Eraro dum agordado de limdato", "The public link will expire no later than {days} days after it is created" : "La publika ligilo senvalidiĝos ne pli malfrue ol {days} tagojn post ĝi kreiĝos", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (fora)", + "{sharee} (email)" : "{sharee} (email)", "This action requires you to confirm your password:" : "Tiu ĉi ago bezonas ke vi konfirmas vian pasvorton:", "Wrong password. Reset it?" : "Falsa pasvorto. Ĉu vi volas rekomenci ĝin?", "Stay logged in" : "Daŭri ensalutinta", diff --git a/core/l10n/es.js b/core/l10n/es.js index ce580b7d2de..7b3d3334574 100644 --- a/core/l10n/es.js +++ b/core/l10n/es.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Modo mantenimiento activado", "Turned off maintenance mode" : "Modo mantenimiento desactivado", "Maintenance mode is kept active" : "El modo mantenimiento aún está activo.", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Esperando a que termine el cron (se vuelve a comprobar en 5 segundos)", "Updating database schema" : "Actualizando el esquema del base de datos", "Updated database" : "Base de datos actualizada", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Comprobar si se puede actualizar el esquema de la base de datos (esto puede tardar bastante tiempo, dependiendo del tamaño de la base de datos)", @@ -160,13 +159,17 @@ OC.L10N.register( "Choose a password for the public link" : "Elija una contraseña para el enlace publico", "Choose a password for the public link or press the \"Enter\" key" : "Escoge una contraseña para el enlace público ", "Copied!" : "¡Copiado!", + "Copy link" : "Copiar enlace", "Not supported!" : "¡No se puede!", "Press ⌘-C to copy." : "Presiona ⌘-C para copiar.", "Press Ctrl-C to copy." : "Presiona Ctrl-C para copiar.", + "Unable to create a link share" : "No se ha podido crear el enlace compartido", + "Unable to toggle this option" : "No se ha podido cambiar esta opción", "Resharing is not allowed" : "No se permite compartir de nuevo", "Share to {name}" : "Compartir a {name}", - "Copy link" : "Copiar enlace", "Link" : "Enlace", + "Hide download" : "Esconder descarga", + "Password protection enforced" : "Protección con contraseña forzada", "Password protect" : "Protección con contraseña", "Allow editing" : "Permitir edición", "Email link to person" : "Enviar enlace por correo electrónico a una persona", @@ -174,12 +177,19 @@ OC.L10N.register( "Allow upload and editing" : "Permitir la subida y la edición", "Read only" : "Solo lectura", "File drop (upload only)" : "Entrega de archivos (solo subida)", + "Expiration date enforced" : "Fecha de expiración forzada", "Set expiration date" : "Establecer fecha de caducidad", "Expiration" : "Caduca el: ", "Expiration date" : "Fecha de caducidad", "Note to recipient" : "Nota al destinatario", + "Unshare" : "Dejar de compartir", + "Delete share link" : "Eliminar enlace compartido", + "Add another link" : "Añadir otro enlace", + "Password protection for links is mandatory" : "La protección con contraseña es obligatoria", "Share link" : "Compartir enlace", - "Enable" : "Habilitar", + "New share link" : "Nuevo enlace compartido", + "Password protect by Talk" : "Protegido con contraseña por Talk", + "Could not unshare" : "No se puede quitar el comparto", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you and {circle} by {owner}" : "Compartido contigo y {circle} por {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Compartido contigo y con la conversación {conversation} por {owner}", @@ -192,16 +202,13 @@ OC.L10N.register( "email" : "email", "conversation" : "conversación", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede eliminar", - "Password protect by Talk" : "Protegido con contraseña por Talk", "Access control" : "Control de acceso", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} compartido por medio de un link", - "Could not unshare" : "No se puede quitar el comparto", "Error while sharing" : "Error al compartir", "Share details could not be loaded for this item." : "No se han podido cargar los detalles de compartición para este elemento.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se necesita al menos {count} carácter para el autocompletado","Se necesitan al menos {count} caracteres para el autocompletado"], @@ -210,12 +217,10 @@ OC.L10N.register( "No users found for {search}" : "No se han encontrado usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Ha ocurrido un error (\"{message}\"). Por favor inténtelo de nuevo", "An error occurred. Please try again" : "Ha ocurrido un error. Por favor inténtelo de nuevo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", "{sharee} (remote group)" : "{sharee} (grupo remoto)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversación)", + "Home" : "Inicio", + "Other" : "Otro", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico...", "Name or federated cloud ID..." : "Nombre o ID de nube federada...", @@ -301,6 +306,7 @@ OC.L10N.register( "Skip to main content" : "Saltar al contenido principal", "Skip to navigation of app" : "Saltar a la navegación de la app", "More apps" : "Más aplicaciones", + "More" : "Más", "More apps menu" : "Menú de otras apps", "Search" : "Buscar", "Reset search" : "Resetear búsqueda", @@ -382,6 +388,9 @@ OC.L10N.register( "Error setting expiration date" : "Error estableciendo fecha de caducidad", "The public link will expire no later than {days} days after it is created" : "El vínculo público no expirará antes de {days} desde que se creó", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} compartido por medio de un link", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas introduciendo un usuario, grupo, ID de nube federada o dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas introduciendo un usuario, grupo o ID de nube federada.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas introduciendo un usuario, grupo o una dirección de correo electrónico.", @@ -413,6 +422,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Estás a punto de conceder a %s acceso a tu cuenta de %s", "Depending on your configuration, this button could also work to trust the domain:" : "Dependiendo de tu configuración, este botón también podría servir para confiar en el dominio:", "Copy URL" : "Copiar URL", + "Enable" : "Habilitar", + "{sharee} (conversation)" : "{sharee} (conversación)", "Please log in before granting %s access to your %s account." : "Por favor, inicie sesión antes de conceder a %s acceso a tu %s cuenta.", "Further information how to configure this can be found in the %sdocumentation%s." : "Más información sobre cómo configurar esto se puede encontrar en la %sdocumentación%s." }, diff --git a/core/l10n/es.json b/core/l10n/es.json index a2be02603df..82f6ec04105 100644 --- a/core/l10n/es.json +++ b/core/l10n/es.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Modo mantenimiento activado", "Turned off maintenance mode" : "Modo mantenimiento desactivado", "Maintenance mode is kept active" : "El modo mantenimiento aún está activo.", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Esperando a que termine el cron (se vuelve a comprobar en 5 segundos)", "Updating database schema" : "Actualizando el esquema del base de datos", "Updated database" : "Base de datos actualizada", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Comprobar si se puede actualizar el esquema de la base de datos (esto puede tardar bastante tiempo, dependiendo del tamaño de la base de datos)", @@ -158,13 +157,17 @@ "Choose a password for the public link" : "Elija una contraseña para el enlace publico", "Choose a password for the public link or press the \"Enter\" key" : "Escoge una contraseña para el enlace público ", "Copied!" : "¡Copiado!", + "Copy link" : "Copiar enlace", "Not supported!" : "¡No se puede!", "Press ⌘-C to copy." : "Presiona ⌘-C para copiar.", "Press Ctrl-C to copy." : "Presiona Ctrl-C para copiar.", + "Unable to create a link share" : "No se ha podido crear el enlace compartido", + "Unable to toggle this option" : "No se ha podido cambiar esta opción", "Resharing is not allowed" : "No se permite compartir de nuevo", "Share to {name}" : "Compartir a {name}", - "Copy link" : "Copiar enlace", "Link" : "Enlace", + "Hide download" : "Esconder descarga", + "Password protection enforced" : "Protección con contraseña forzada", "Password protect" : "Protección con contraseña", "Allow editing" : "Permitir edición", "Email link to person" : "Enviar enlace por correo electrónico a una persona", @@ -172,12 +175,19 @@ "Allow upload and editing" : "Permitir la subida y la edición", "Read only" : "Solo lectura", "File drop (upload only)" : "Entrega de archivos (solo subida)", + "Expiration date enforced" : "Fecha de expiración forzada", "Set expiration date" : "Establecer fecha de caducidad", "Expiration" : "Caduca el: ", "Expiration date" : "Fecha de caducidad", "Note to recipient" : "Nota al destinatario", + "Unshare" : "Dejar de compartir", + "Delete share link" : "Eliminar enlace compartido", + "Add another link" : "Añadir otro enlace", + "Password protection for links is mandatory" : "La protección con contraseña es obligatoria", "Share link" : "Compartir enlace", - "Enable" : "Habilitar", + "New share link" : "Nuevo enlace compartido", + "Password protect by Talk" : "Protegido con contraseña por Talk", + "Could not unshare" : "No se puede quitar el comparto", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you and {circle} by {owner}" : "Compartido contigo y {circle} por {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Compartido contigo y con la conversación {conversation} por {owner}", @@ -190,16 +200,13 @@ "email" : "email", "conversation" : "conversación", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede eliminar", - "Password protect by Talk" : "Protegido con contraseña por Talk", "Access control" : "Control de acceso", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} compartido por medio de un link", - "Could not unshare" : "No se puede quitar el comparto", "Error while sharing" : "Error al compartir", "Share details could not be loaded for this item." : "No se han podido cargar los detalles de compartición para este elemento.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se necesita al menos {count} carácter para el autocompletado","Se necesitan al menos {count} caracteres para el autocompletado"], @@ -208,12 +215,10 @@ "No users found for {search}" : "No se han encontrado usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Ha ocurrido un error (\"{message}\"). Por favor inténtelo de nuevo", "An error occurred. Please try again" : "Ha ocurrido un error. Por favor inténtelo de nuevo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", "{sharee} (remote group)" : "{sharee} (grupo remoto)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversación)", + "Home" : "Inicio", + "Other" : "Otro", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico...", "Name or federated cloud ID..." : "Nombre o ID de nube federada...", @@ -299,6 +304,7 @@ "Skip to main content" : "Saltar al contenido principal", "Skip to navigation of app" : "Saltar a la navegación de la app", "More apps" : "Más aplicaciones", + "More" : "Más", "More apps menu" : "Menú de otras apps", "Search" : "Buscar", "Reset search" : "Resetear búsqueda", @@ -380,6 +386,9 @@ "Error setting expiration date" : "Error estableciendo fecha de caducidad", "The public link will expire no later than {days} days after it is created" : "El vínculo público no expirará antes de {days} desde que se creó", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} compartido por medio de un link", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas introduciendo un usuario, grupo, ID de nube federada o dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas introduciendo un usuario, grupo o ID de nube federada.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas introduciendo un usuario, grupo o una dirección de correo electrónico.", @@ -411,6 +420,8 @@ "You are about to grant %s access to your %s account." : "Estás a punto de conceder a %s acceso a tu cuenta de %s", "Depending on your configuration, this button could also work to trust the domain:" : "Dependiendo de tu configuración, este botón también podría servir para confiar en el dominio:", "Copy URL" : "Copiar URL", + "Enable" : "Habilitar", + "{sharee} (conversation)" : "{sharee} (conversación)", "Please log in before granting %s access to your %s account." : "Por favor, inicie sesión antes de conceder a %s acceso a tu %s cuenta.", "Further information how to configure this can be found in the %sdocumentation%s." : "Más información sobre cómo configurar esto se puede encontrar en la %sdocumentación%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/es_419.js b/core/l10n/es_419.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_419.js +++ b/core/l10n/es_419.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_419.json b/core/l10n/es_419.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_419.json +++ b/core/l10n/es_419.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_AR.js b/core/l10n/es_AR.js index 88229c30d51..6ea872c8ec5 100644 --- a/core/l10n/es_AR.js +++ b/core/l10n/es_AR.js @@ -124,7 +124,9 @@ OC.L10N.register( "Set expiration date" : "Establecer la fecha de expiración", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir link", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido con usted y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido con usted por {owner}", "Choose a password for the mail share" : "Establecer una contraseña para el elemento compartido por correo", @@ -132,14 +134,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -147,9 +147,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Favor de volver a intentar", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -265,6 +262,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "El link público expirará a los {days} días de haber sido creado", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compatido mediante un link", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparta con otras personas ingresando un usuario, un grupo, un ID de nube federado o una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparta con otras personas ingresando un usuario, un grupo o un ID de nube federado.", "Share with other people by entering a user or group or an email address." : "Comparta con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_AR.json b/core/l10n/es_AR.json index 1036a3cba25..400692c42a5 100644 --- a/core/l10n/es_AR.json +++ b/core/l10n/es_AR.json @@ -122,7 +122,9 @@ "Set expiration date" : "Establecer la fecha de expiración", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir link", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido con usted y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido con usted por {owner}", "Choose a password for the mail share" : "Establecer una contraseña para el elemento compartido por correo", @@ -130,14 +132,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -145,9 +145,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Favor de volver a intentar", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -263,6 +260,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "El link público expirará a los {days} días de haber sido creado", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compatido mediante un link", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparta con otras personas ingresando un usuario, un grupo, un ID de nube federado o una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparta con otras personas ingresando un usuario, un grupo o un ID de nube federado.", "Share with other people by entering a user or group or an email address." : "Comparta con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_CL.js b/core/l10n/es_CL.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_CL.js +++ b/core/l10n/es_CL.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_CL.json b/core/l10n/es_CL.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_CL.json +++ b/core/l10n/es_CL.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_CO.js b/core/l10n/es_CO.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_CO.js +++ b/core/l10n/es_CO.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_CO.json b/core/l10n/es_CO.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_CO.json +++ b/core/l10n/es_CO.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_CR.js b/core/l10n/es_CR.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_CR.js +++ b/core/l10n/es_CR.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_CR.json b/core/l10n/es_CR.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_CR.json +++ b/core/l10n/es_CR.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_DO.js b/core/l10n/es_DO.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_DO.js +++ b/core/l10n/es_DO.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_DO.json b/core/l10n/es_DO.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_DO.json +++ b/core/l10n/es_DO.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_EC.js b/core/l10n/es_EC.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_EC.js +++ b/core/l10n/es_EC.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_EC.json b/core/l10n/es_EC.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_EC.json +++ b/core/l10n/es_EC.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_GT.js b/core/l10n/es_GT.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_GT.js +++ b/core/l10n/es_GT.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_GT.json b/core/l10n/es_GT.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_GT.json +++ b/core/l10n/es_GT.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_HN.js b/core/l10n/es_HN.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_HN.js +++ b/core/l10n/es_HN.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_HN.json b/core/l10n/es_HN.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_HN.json +++ b/core/l10n/es_HN.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_MX.js b/core/l10n/es_MX.js index cfa292606c7..61540f1b740 100644 --- a/core/l10n/es_MX.js +++ b/core/l10n/es_MX.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_MX.json b/core/l10n/es_MX.json index ea929476c1f..c4f6d8104c2 100644 --- a/core/l10n/es_MX.json +++ b/core/l10n/es_MX.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_NI.js b/core/l10n/es_NI.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_NI.js +++ b/core/l10n/es_NI.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_NI.json b/core/l10n/es_NI.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_NI.json +++ b/core/l10n/es_NI.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PA.js b/core/l10n/es_PA.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_PA.js +++ b/core/l10n/es_PA.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PA.json b/core/l10n/es_PA.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_PA.json +++ b/core/l10n/es_PA.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PE.js b/core/l10n/es_PE.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_PE.js +++ b/core/l10n/es_PE.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PE.json b/core/l10n/es_PE.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_PE.json +++ b/core/l10n/es_PE.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PR.js b/core/l10n/es_PR.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_PR.js +++ b/core/l10n/es_PR.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PR.json b/core/l10n/es_PR.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_PR.json +++ b/core/l10n/es_PR.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PY.js b/core/l10n/es_PY.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_PY.js +++ b/core/l10n/es_PY.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_PY.json b/core/l10n/es_PY.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_PY.json +++ b/core/l10n/es_PY.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_SV.js b/core/l10n/es_SV.js index 28531d48743..b055a44316b 100644 --- a/core/l10n/es_SV.js +++ b/core/l10n/es_SV.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -170,9 +170,6 @@ OC.L10N.register( "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -323,6 +320,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_SV.json b/core/l10n/es_SV.json index 9ec18d03f47..f623d6901de 100644 --- a/core/l10n/es_SV.json +++ b/core/l10n/es_SV.json @@ -144,7 +144,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -168,9 +168,6 @@ "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred (\"{message}\"). Please try again" : "Se presentó un error (\"{message}\"). Por favor vuelve a intentarlo", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -321,6 +318,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_UY.js b/core/l10n/es_UY.js index f44a641ce1e..799022f8121 100644 --- a/core/l10n/es_UY.js +++ b/core/l10n/es_UY.js @@ -144,7 +144,9 @@ OC.L10N.register( "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -152,14 +154,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -167,9 +167,6 @@ OC.L10N.register( "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -294,6 +291,9 @@ OC.L10N.register( "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/es_UY.json b/core/l10n/es_UY.json index 62d866f1327..bfa3e21c192 100644 --- a/core/l10n/es_UY.json +++ b/core/l10n/es_UY.json @@ -142,7 +142,9 @@ "Set expiration date" : "Selecciona la vigencia de tu archivo", "Expiration" : "Expiración", "Expiration date" : "Fecha de expiración", + "Unshare" : "Dejar de compartir", "Share link" : "Compartir liga", + "Could not unshare" : "No fue posible dejar de compartir", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", "Shared with you by {owner}" : "Compartido contigo por {owner}", "Choose a password for the mail share" : "Elige una contraseña para el elemento compartido por correo", @@ -150,14 +152,12 @@ "remote" : "remoto", "email" : "correo electrónico", "shared by {sharer}" : "compartido por {sharer}", - "Unshare" : "Dejar de compartir", "Can reshare" : "Puede volver a compartir", "Can edit" : "Puede editar", "Can create" : "Puede crear", "Can change" : "Puede cambiar", "Can delete" : "Puede borrar", "Access control" : "Control de acceso", - "Could not unshare" : "No fue posible dejar de compartir", "Error while sharing" : "Se presentó un error al compartir", "Share details could not be loaded for this item." : "Los detalles del recurso compartido no se pudieron cargar para este elemento. ", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Se requiere de la menos {count} caracter para el auto completar","Se requieren de la menos {count} caracteres para el auto completar"], @@ -165,9 +165,6 @@ "No users or groups found for {search}" : "No se encontraron usuarios o gurpos para {search}", "No users found for {search}" : "No se encontraron usuarios para {search}", "An error occurred. Please try again" : "Se presentó un error. Por favor vuelve a intentarlo", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (correo electrónico)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Compartir", "Name or email address..." : "Nombre o dirección de correo electrónico", @@ -292,6 +289,9 @@ "Error setting expiration date" : "Se presentó un error al establecer la fecha de expiración", "The public link will expire no later than {days} days after it is created" : "La liga pública expirará a los {days} días de haber sido creada", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha compartido mediante una liga", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (correo electrónico)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Comparte con otras personas ingresando una dirección de correo electrónico.", "Share with other people by entering a user or group or a federated cloud ID." : "Comparte con otras personas ingresando un usuario o un grupo.", "Share with other people by entering a user or group or an email address." : "Comparte con otras personas ingresando un usuario, un grupo o una dirección de correo electrónico.", diff --git a/core/l10n/et_EE.js b/core/l10n/et_EE.js index f52158fff67..0eb90a0f95b 100644 --- a/core/l10n/et_EE.js +++ b/core/l10n/et_EE.js @@ -131,7 +131,9 @@ OC.L10N.register( "Set expiration date" : "Määra aegumise kuupäev", "Expiration" : "Aegumine", "Expiration date" : "Aegumise kuupäev", + "Unshare" : "Lõpeta jagamine", "Share link" : "Jaga linki", + "Could not unshare" : "Jagamise lõpetamine ebaõnnestus", "Shared with you and the group {group} by {owner}" : "Jagatud sinu ja {group} grupiga {owner} poolt", "Shared with you by {owner}" : "Sinuga jagas {owner}", "Choose a password for the mail share" : "Vali parool e-postiga jagamisel", @@ -139,23 +141,18 @@ OC.L10N.register( "remote" : "kaug", "email" : "e-post", "shared by {sharer}" : "jagatud kasutajalt {sharer}", - "Unshare" : "Lõpeta jagamine", "Can reshare" : "Võib edasi jagada", "Can edit" : "Võib redigeerida", "Can create" : "Võib luua", "Can change" : "Võib muuta", "Can delete" : "Võib kustutada", "Access control" : "Ligipääsukontroll", - "Could not unshare" : "Jagamise lõpetamine ebaõnnestus", "Error while sharing" : "Viga jagamisel", "Share details could not be loaded for this item." : "Selle üksuse jagamise detaile ei õnnestunud laadida.", "This list is maybe truncated - please refine your search term to see more results." : "See nimekiri võib olla kärbitud - palun täpsusta oma otsingut, et näha rohkem tulemusi.", "No users or groups found for {search}" : "Otsingu {search} põhjal kasutajaid ega gruppe ei leitud", "No users found for {search}" : "Otsingu {search} põhjal kasutajaid ei leitud", "An error occurred. Please try again" : "Tekkis tõrge. Palun proovi uuesti", - "{sharee} (group)" : "{sharee} (grupp)", - "{sharee} (remote)" : "{sharee} (mujal serveris)", - "{sharee} (email)" : "{sharee} (e-post)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Jaga", "Name or email address..." : "Nimi või e-posti aadress", @@ -275,6 +272,9 @@ OC.L10N.register( "Error setting expiration date" : "Viga aegumise kuupäeva määramisel", "The public link will expire no later than {days} days after it is created" : "Avalik link aegub mitte hiljem kui pärast {days} päeva selle loomist", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} lingiga jagatud", + "{sharee} (group)" : "{sharee} (grupp)", + "{sharee} (remote)" : "{sharee} (mujal serveris)", + "{sharee} (email)" : "{sharee} (e-post)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Jaga teiste inimestega sisestades kasutaja või grupi, liitpilve ID või e-posti aadressi.", "Share with other people by entering a user or group or a federated cloud ID." : "Jaga teiste inimestega, sisestades kasutaja või grupi või liitpilve ID.", "Share with other people by entering a user or group or an email address." : "Jaga teiste inimestega, sisestades kasutaja, grupi või e-posti aadressi.", diff --git a/core/l10n/et_EE.json b/core/l10n/et_EE.json index 7ae2161a144..eb44383e7a1 100644 --- a/core/l10n/et_EE.json +++ b/core/l10n/et_EE.json @@ -129,7 +129,9 @@ "Set expiration date" : "Määra aegumise kuupäev", "Expiration" : "Aegumine", "Expiration date" : "Aegumise kuupäev", + "Unshare" : "Lõpeta jagamine", "Share link" : "Jaga linki", + "Could not unshare" : "Jagamise lõpetamine ebaõnnestus", "Shared with you and the group {group} by {owner}" : "Jagatud sinu ja {group} grupiga {owner} poolt", "Shared with you by {owner}" : "Sinuga jagas {owner}", "Choose a password for the mail share" : "Vali parool e-postiga jagamisel", @@ -137,23 +139,18 @@ "remote" : "kaug", "email" : "e-post", "shared by {sharer}" : "jagatud kasutajalt {sharer}", - "Unshare" : "Lõpeta jagamine", "Can reshare" : "Võib edasi jagada", "Can edit" : "Võib redigeerida", "Can create" : "Võib luua", "Can change" : "Võib muuta", "Can delete" : "Võib kustutada", "Access control" : "Ligipääsukontroll", - "Could not unshare" : "Jagamise lõpetamine ebaõnnestus", "Error while sharing" : "Viga jagamisel", "Share details could not be loaded for this item." : "Selle üksuse jagamise detaile ei õnnestunud laadida.", "This list is maybe truncated - please refine your search term to see more results." : "See nimekiri võib olla kärbitud - palun täpsusta oma otsingut, et näha rohkem tulemusi.", "No users or groups found for {search}" : "Otsingu {search} põhjal kasutajaid ega gruppe ei leitud", "No users found for {search}" : "Otsingu {search} põhjal kasutajaid ei leitud", "An error occurred. Please try again" : "Tekkis tõrge. Palun proovi uuesti", - "{sharee} (group)" : "{sharee} (grupp)", - "{sharee} (remote)" : "{sharee} (mujal serveris)", - "{sharee} (email)" : "{sharee} (e-post)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Jaga", "Name or email address..." : "Nimi või e-posti aadress", @@ -273,6 +270,9 @@ "Error setting expiration date" : "Viga aegumise kuupäeva määramisel", "The public link will expire no later than {days} days after it is created" : "Avalik link aegub mitte hiljem kui pärast {days} päeva selle loomist", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} lingiga jagatud", + "{sharee} (group)" : "{sharee} (grupp)", + "{sharee} (remote)" : "{sharee} (mujal serveris)", + "{sharee} (email)" : "{sharee} (e-post)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Jaga teiste inimestega sisestades kasutaja või grupi, liitpilve ID või e-posti aadressi.", "Share with other people by entering a user or group or a federated cloud ID." : "Jaga teiste inimestega, sisestades kasutaja või grupi või liitpilve ID.", "Share with other people by entering a user or group or an email address." : "Jaga teiste inimestega, sisestades kasutaja, grupi või e-posti aadressi.", diff --git a/core/l10n/eu.js b/core/l10n/eu.js index 041313326a6..bb24343efea 100644 --- a/core/l10n/eu.js +++ b/core/l10n/eu.js @@ -127,7 +127,9 @@ OC.L10N.register( "Set expiration date" : "Ezarri muga data", "Expiration" : "Iraungitzea", "Expiration date" : "Muga data", + "Unshare" : "Ez partekatu", "Share link" : "Partekatu esteka", + "Could not unshare" : "Ezin izan da despartekatu", "Shared with you and the group {group} by {owner}" : "{owner}-k zu eta {group} taldearekin partekatuta", "Shared with you by {owner}" : "{owner}-k zurekin partekatuta", "Choose a password for the mail share" : "Hautatu pasahitz bat posta partekatzeko", @@ -135,14 +137,12 @@ OC.L10N.register( "remote" : "urrunekoa", "email" : "posta-elektronikoa", "shared by {sharer}" : "{sharer}-(e)k partekatu du", - "Unshare" : "Ez partekatu", "Can reshare" : "Birparteka daiteke", "Can edit" : "Editatu dezake", "Can create" : "sortu dezake", "Can change" : "Aldatu dezake", "Can delete" : "Ezabatu dezake", "Access control" : "Sarrera kontrola", - "Could not unshare" : "Ezin izan da despartekatu", "Error while sharing" : "Errore bat egon da elkarbanatzean", "Share details could not be loaded for this item." : "Partekatze xehetasunak ezin izan dira elementu honentzat kargatu.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Autosaketaren funtziorako {count} karaketere gutxienez behar dira","Autosaketaren funtziorako {count} karaketere gutxienez behar dira"], @@ -150,9 +150,6 @@ OC.L10N.register( "No users or groups found for {search}" : "Ez dira {search} -rentzat erabiltzaile edo talderik aurkitu", "No users found for {search}" : "Ez dira {search} -rentzat erabiltzailerik aurkitu", "An error occurred. Please try again" : "Errore bat gertatu da. Saiatu berriro.", - "{sharee} (group)" : "{sharee} (taldea)", - "{sharee} (remote)" : "{sharee} (urrunekoa)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {jabea})", "Share" : "Partekatu", "Name or email address..." : "Izena edo e-posta helbidea...", @@ -273,6 +270,9 @@ OC.L10N.register( "Error setting expiration date" : "Errore bat egon da muga data ezartzean", "The public link will expire no later than {days} days after it is created" : "Esteka publikoak iraungi egingo du, askoz jota, sortu eta {days} egunetara.", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} esteka bidez partekatuta", + "{sharee} (group)" : "{sharee} (taldea)", + "{sharee} (remote)" : "{sharee} (urrunekoa)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Parteka ezazu jendearekin taldeko erabiltzailea, federatutako hodei baten IDa edo e-posta helbide bat sartuta.", "Share with other people by entering a user or group or a federated cloud ID." : "Parteka ezazu jendearekin taldeko erabiltzailea edo federatutako hodei baten IDa sartuta.", "Share with other people by entering a user or group or an email address." : "Parteka ezazu jendearekin taldeko erabiltzailea edo e-posta helbide bat sartuta.", diff --git a/core/l10n/eu.json b/core/l10n/eu.json index 37d0faa64b9..3cb0e72a34a 100644 --- a/core/l10n/eu.json +++ b/core/l10n/eu.json @@ -125,7 +125,9 @@ "Set expiration date" : "Ezarri muga data", "Expiration" : "Iraungitzea", "Expiration date" : "Muga data", + "Unshare" : "Ez partekatu", "Share link" : "Partekatu esteka", + "Could not unshare" : "Ezin izan da despartekatu", "Shared with you and the group {group} by {owner}" : "{owner}-k zu eta {group} taldearekin partekatuta", "Shared with you by {owner}" : "{owner}-k zurekin partekatuta", "Choose a password for the mail share" : "Hautatu pasahitz bat posta partekatzeko", @@ -133,14 +135,12 @@ "remote" : "urrunekoa", "email" : "posta-elektronikoa", "shared by {sharer}" : "{sharer}-(e)k partekatu du", - "Unshare" : "Ez partekatu", "Can reshare" : "Birparteka daiteke", "Can edit" : "Editatu dezake", "Can create" : "sortu dezake", "Can change" : "Aldatu dezake", "Can delete" : "Ezabatu dezake", "Access control" : "Sarrera kontrola", - "Could not unshare" : "Ezin izan da despartekatu", "Error while sharing" : "Errore bat egon da elkarbanatzean", "Share details could not be loaded for this item." : "Partekatze xehetasunak ezin izan dira elementu honentzat kargatu.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Autosaketaren funtziorako {count} karaketere gutxienez behar dira","Autosaketaren funtziorako {count} karaketere gutxienez behar dira"], @@ -148,9 +148,6 @@ "No users or groups found for {search}" : "Ez dira {search} -rentzat erabiltzaile edo talderik aurkitu", "No users found for {search}" : "Ez dira {search} -rentzat erabiltzailerik aurkitu", "An error occurred. Please try again" : "Errore bat gertatu da. Saiatu berriro.", - "{sharee} (group)" : "{sharee} (taldea)", - "{sharee} (remote)" : "{sharee} (urrunekoa)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {jabea})", "Share" : "Partekatu", "Name or email address..." : "Izena edo e-posta helbidea...", @@ -271,6 +268,9 @@ "Error setting expiration date" : "Errore bat egon da muga data ezartzean", "The public link will expire no later than {days} days after it is created" : "Esteka publikoak iraungi egingo du, askoz jota, sortu eta {days} egunetara.", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} esteka bidez partekatuta", + "{sharee} (group)" : "{sharee} (taldea)", + "{sharee} (remote)" : "{sharee} (urrunekoa)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Parteka ezazu jendearekin taldeko erabiltzailea, federatutako hodei baten IDa edo e-posta helbide bat sartuta.", "Share with other people by entering a user or group or a federated cloud ID." : "Parteka ezazu jendearekin taldeko erabiltzailea edo federatutako hodei baten IDa sartuta.", "Share with other people by entering a user or group or an email address." : "Parteka ezazu jendearekin taldeko erabiltzailea edo e-posta helbide bat sartuta.", diff --git a/core/l10n/fa.js b/core/l10n/fa.js index 6c5cd28899c..69a8c0368a2 100644 --- a/core/l10n/fa.js +++ b/core/l10n/fa.js @@ -127,7 +127,9 @@ OC.L10N.register( "Set expiration date" : "تنظیم تاریخ انقضا", "Expiration" : "تاریخ انقضا", "Expiration date" : "تاریخ انقضا", + "Unshare" : "لغو اشتراک", "Share link" : "اشتراک گذاشتن لینک", + "Could not unshare" : "اشتراک گذاری بازگردانده نشد", "Shared with you and the group {group} by {owner}" : "به اشتراک گذاشته شده با شما و گروه {گروه} توسط {دارنده}", "Shared with you by {owner}" : "به اشتراک گذاشته شده با شما توسط { دارنده}", "Choose a password for the mail share" : "یک رمز عبور برای اشتراک ایمیل انتخاب کنید", @@ -135,14 +137,12 @@ OC.L10N.register( "remote" : "از راه دور", "email" : "ایمیل", "shared by {sharer}" : "اشتراک گذاشته شده توسط {sharer}", - "Unshare" : "لغو اشتراک", "Can reshare" : "می توان مجددا به اشتراک گذاشت", "Can edit" : "می توان ویرایش کرد", "Can create" : "میتوان ایجاد کرد", "Can change" : "می توان تغییر داد", "Can delete" : "می توان حذف کرد", "Access control" : "کنترل دسترسی", - "Could not unshare" : "اشتراک گذاری بازگردانده نشد", "Error while sharing" : "خطا درحال به اشتراک گذاشتن", "Share details could not be loaded for this item." : "جزئیات اشتراک گذاری برای این مورد قابل بارگذاری نیست.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["برای تکمیل خودکار لازم است حداقل {count} کاراکتر وجود داشته باشد","برای تکمیل خودکار لازم است حداقل {count} کاراکتر وجود داشته باشد"], @@ -150,9 +150,6 @@ OC.L10N.register( "No users or groups found for {search}" : "هیچ کاربری یا گروهی یافت نشد {search}", "No users found for {search}" : "هیچ کاربری با جستجوی {search} یافت نشد", "An error occurred. Please try again" : "یک خطا رخ داده است، لطفا مجددا تلاش کنید", - "{sharee} (group)" : "{sharee} (group)", - "{sharee} (remote)" : "{sharee} (remote)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "اشتراکگذاری", "Name or email address..." : "نام یا آدرس ایمیل ...", @@ -257,6 +254,9 @@ OC.L10N.register( "Error setting expiration date" : "خطا در تنظیم تاریخ انقضا", "The public link will expire no later than {days} days after it is created" : "لینک عمومی پس از {days} روز پس از ایجاد منقضی خواهد شد", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} به اشتراک گذاشته شده از طریق لینک", + "{sharee} (group)" : "{sharee} (group)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "با وارد کردن یک کاربر یا گروه، شناسه Federated Cloud یا آدرس ایمیل با دیگران به اشتراک بگذارید.", "Share with other people by entering a user or group or a federated cloud ID." : "با وارد کردن یک کاربر یا گروه یا شناسه Federated Cloud با افراد دیگر به اشتراک بگذارید.", "Share with other people by entering a user or group or an email address." : "با وارد کردن یک کاربر یا گروه یا یک آدرس ایمیل با افراد دیگر به اشتراک بگذارید.", diff --git a/core/l10n/fa.json b/core/l10n/fa.json index 24e8130b426..92b823a4f01 100644 --- a/core/l10n/fa.json +++ b/core/l10n/fa.json @@ -125,7 +125,9 @@ "Set expiration date" : "تنظیم تاریخ انقضا", "Expiration" : "تاریخ انقضا", "Expiration date" : "تاریخ انقضا", + "Unshare" : "لغو اشتراک", "Share link" : "اشتراک گذاشتن لینک", + "Could not unshare" : "اشتراک گذاری بازگردانده نشد", "Shared with you and the group {group} by {owner}" : "به اشتراک گذاشته شده با شما و گروه {گروه} توسط {دارنده}", "Shared with you by {owner}" : "به اشتراک گذاشته شده با شما توسط { دارنده}", "Choose a password for the mail share" : "یک رمز عبور برای اشتراک ایمیل انتخاب کنید", @@ -133,14 +135,12 @@ "remote" : "از راه دور", "email" : "ایمیل", "shared by {sharer}" : "اشتراک گذاشته شده توسط {sharer}", - "Unshare" : "لغو اشتراک", "Can reshare" : "می توان مجددا به اشتراک گذاشت", "Can edit" : "می توان ویرایش کرد", "Can create" : "میتوان ایجاد کرد", "Can change" : "می توان تغییر داد", "Can delete" : "می توان حذف کرد", "Access control" : "کنترل دسترسی", - "Could not unshare" : "اشتراک گذاری بازگردانده نشد", "Error while sharing" : "خطا درحال به اشتراک گذاشتن", "Share details could not be loaded for this item." : "جزئیات اشتراک گذاری برای این مورد قابل بارگذاری نیست.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["برای تکمیل خودکار لازم است حداقل {count} کاراکتر وجود داشته باشد","برای تکمیل خودکار لازم است حداقل {count} کاراکتر وجود داشته باشد"], @@ -148,9 +148,6 @@ "No users or groups found for {search}" : "هیچ کاربری یا گروهی یافت نشد {search}", "No users found for {search}" : "هیچ کاربری با جستجوی {search} یافت نشد", "An error occurred. Please try again" : "یک خطا رخ داده است، لطفا مجددا تلاش کنید", - "{sharee} (group)" : "{sharee} (group)", - "{sharee} (remote)" : "{sharee} (remote)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "اشتراکگذاری", "Name or email address..." : "نام یا آدرس ایمیل ...", @@ -255,6 +252,9 @@ "Error setting expiration date" : "خطا در تنظیم تاریخ انقضا", "The public link will expire no later than {days} days after it is created" : "لینک عمومی پس از {days} روز پس از ایجاد منقضی خواهد شد", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} به اشتراک گذاشته شده از طریق لینک", + "{sharee} (group)" : "{sharee} (group)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "با وارد کردن یک کاربر یا گروه، شناسه Federated Cloud یا آدرس ایمیل با دیگران به اشتراک بگذارید.", "Share with other people by entering a user or group or a federated cloud ID." : "با وارد کردن یک کاربر یا گروه یا شناسه Federated Cloud با افراد دیگر به اشتراک بگذارید.", "Share with other people by entering a user or group or an email address." : "با وارد کردن یک کاربر یا گروه یا یک آدرس ایمیل با افراد دیگر به اشتراک بگذارید.", diff --git a/core/l10n/fi.js b/core/l10n/fi.js index 8cbbf37cc80..c26b742721e 100644 --- a/core/l10n/fi.js +++ b/core/l10n/fi.js @@ -34,7 +34,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Siirrytty huoltotilaan", "Turned off maintenance mode" : "Poistuttu huoltotilasta", "Maintenance mode is kept active" : "Huoltotila pidetään aktiivisena", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Odotetaan cronin valmistuvan (tarkista uudelleen 5 sekunnin päästä) …", "Updating database schema" : "Päivitetään tietokannan skeemaa", "Updated database" : "Tietokanta päivitetty", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Tarkistetaan, onko tietokannan skeemaa mahdollista päivittää (tämä saattaa kestää kauan riippuen tietokannan koosta)", @@ -137,12 +136,12 @@ OC.L10N.register( "Choose a password for the public link" : "Valitse salasana julkiselle linkille", "Choose a password for the public link or press the \"Enter\" key" : "Valitse salasana julkiselle linkille tai paina \"Enter\" näppäintä", "Copied!" : "Kopioitu!", + "Copy link" : "Kopioi linkki", "Not supported!" : "Ei tuettu!", "Press ⌘-C to copy." : "Paina ⌘-C kopioidaksesi.", "Press Ctrl-C to copy." : "Paina Ctrl-C kopioidaksesi.", "Resharing is not allowed" : "Jakaminen uudelleen ei ole sallittu", "Share to {name}" : "Jaa henkilölle {name}", - "Copy link" : "Kopioi linkki", "Link" : "Linkki", "Password protect" : "Suojaa salasanalla", "Allow editing" : "Salli muokkaus", @@ -154,8 +153,9 @@ OC.L10N.register( "Set expiration date" : "Aseta vanhenemispäivä", "Expiration" : "Vanheneminen", "Expiration date" : "Vanhenemispäivä", + "Unshare" : "Lopeta jakaminen", "Share link" : "Jaa linkki", - "Enable" : "Ota käyttöön", + "Could not unshare" : "Jakamisen lopettaminen epäonnistui", "Shared with you and the group {group} by {owner}" : "Jaettu sinun ja ryhmän {group} kanssa käyttäjältä {owner}", "Shared with you by {owner}" : "Jaettu kanssasi käyttäjältä {owner}", "Choose a password for the mail share" : "Valitse salasana sähköpostijaolle", @@ -164,14 +164,12 @@ OC.L10N.register( "remote group" : "etäryhmä", "email" : "sähköposti", "shared by {sharer}" : "jakanut {sharer}", - "Unshare" : "Lopeta jakaminen", "Can reshare" : "Voi uudelleenjakaa", "Can edit" : "Voi muokata", "Can create" : "Voi luoda", "Can change" : "Voi vaihtaa", "Can delete" : "Voi poistaa", "Access control" : "Pääsynhallinta", - "Could not unshare" : "Jakamisen lopettaminen epäonnistui", "Error while sharing" : "Virhe jaettaessa", "Share details could not be loaded for this item." : "Tämän kohteen jakamistietoja ei voitu ladata.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Vähintään {count} kirjain vaaditaan automaattiseen täydentämiseen","Vähintään {count} kirjainta vaaditaan automaattiseen täydentämiseen"], @@ -180,9 +178,6 @@ OC.L10N.register( "No users found for {search}" : "Haulla {search} ei löytynyt käyttäjiä", "An error occurred (\"{message}\"). Please try again" : "Tapahtui virhe (\"{message}\"). Yritä uudestaan", "An error occurred. Please try again" : "Tapahtui virhe, yritä uudelleen", - "{sharee} (group)" : "{sharee} (ryhmä)", - "{sharee} (remote)" : "{sharee} (etä)", - "{sharee} (email)" : "{sharee} (sähköposti)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Jaa", "Name or email address..." : "Nimi tai sähköpostiosoite...", @@ -332,6 +327,9 @@ OC.L10N.register( "Error setting expiration date" : "Virhe vanhenemispäivää asetettaessa", "The public link will expire no later than {days} days after it is created" : "Julkinen linkki vanhenee {days} päivän jälkeen sen luomisesta", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} jakoi linkillä", + "{sharee} (group)" : "{sharee} (ryhmä)", + "{sharee} (remote)" : "{sharee} (etä)", + "{sharee} (email)" : "{sharee} (sähköposti)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Jaa muille kirjoittamalla käyttäjä tai ryhmä, federoidun pilven tunniste tai sähköpostiosoite.", "Share with other people by entering a user or group or a federated cloud ID." : "Jaa muille kirjoittamalla käyttäjä, ryhmä tai federoidun pilven tunniste.", "Share with other people by entering a user or group or an email address." : "Jaa muille kirjoittamalla käyttäjä, ryhmä tai sähköpostiosoite.", @@ -361,6 +359,7 @@ OC.L10N.register( "Back to log in" : "Palaa kirjautumiseen", "You are about to grant %s access to your %s account." : "Olet antamassa lupaa laitteelle %s päästä sinun %s tilille.", "Depending on your configuration, this button could also work to trust the domain:" : "Asetuksista riippuen, ylläpitäjänä saatat pystyä alla olevalla painikkeella lisäämään tämän verkkotunnuksen luotetuksi.", - "Copy URL" : "Kopioi osoite" + "Copy URL" : "Kopioi osoite", + "Enable" : "Ota käyttöön" }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/fi.json b/core/l10n/fi.json index 22bcbca652b..a8e48345f4b 100644 --- a/core/l10n/fi.json +++ b/core/l10n/fi.json @@ -32,7 +32,6 @@ "Turned on maintenance mode" : "Siirrytty huoltotilaan", "Turned off maintenance mode" : "Poistuttu huoltotilasta", "Maintenance mode is kept active" : "Huoltotila pidetään aktiivisena", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Odotetaan cronin valmistuvan (tarkista uudelleen 5 sekunnin päästä) …", "Updating database schema" : "Päivitetään tietokannan skeemaa", "Updated database" : "Tietokanta päivitetty", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Tarkistetaan, onko tietokannan skeemaa mahdollista päivittää (tämä saattaa kestää kauan riippuen tietokannan koosta)", @@ -135,12 +134,12 @@ "Choose a password for the public link" : "Valitse salasana julkiselle linkille", "Choose a password for the public link or press the \"Enter\" key" : "Valitse salasana julkiselle linkille tai paina \"Enter\" näppäintä", "Copied!" : "Kopioitu!", + "Copy link" : "Kopioi linkki", "Not supported!" : "Ei tuettu!", "Press ⌘-C to copy." : "Paina ⌘-C kopioidaksesi.", "Press Ctrl-C to copy." : "Paina Ctrl-C kopioidaksesi.", "Resharing is not allowed" : "Jakaminen uudelleen ei ole sallittu", "Share to {name}" : "Jaa henkilölle {name}", - "Copy link" : "Kopioi linkki", "Link" : "Linkki", "Password protect" : "Suojaa salasanalla", "Allow editing" : "Salli muokkaus", @@ -152,8 +151,9 @@ "Set expiration date" : "Aseta vanhenemispäivä", "Expiration" : "Vanheneminen", "Expiration date" : "Vanhenemispäivä", + "Unshare" : "Lopeta jakaminen", "Share link" : "Jaa linkki", - "Enable" : "Ota käyttöön", + "Could not unshare" : "Jakamisen lopettaminen epäonnistui", "Shared with you and the group {group} by {owner}" : "Jaettu sinun ja ryhmän {group} kanssa käyttäjältä {owner}", "Shared with you by {owner}" : "Jaettu kanssasi käyttäjältä {owner}", "Choose a password for the mail share" : "Valitse salasana sähköpostijaolle", @@ -162,14 +162,12 @@ "remote group" : "etäryhmä", "email" : "sähköposti", "shared by {sharer}" : "jakanut {sharer}", - "Unshare" : "Lopeta jakaminen", "Can reshare" : "Voi uudelleenjakaa", "Can edit" : "Voi muokata", "Can create" : "Voi luoda", "Can change" : "Voi vaihtaa", "Can delete" : "Voi poistaa", "Access control" : "Pääsynhallinta", - "Could not unshare" : "Jakamisen lopettaminen epäonnistui", "Error while sharing" : "Virhe jaettaessa", "Share details could not be loaded for this item." : "Tämän kohteen jakamistietoja ei voitu ladata.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Vähintään {count} kirjain vaaditaan automaattiseen täydentämiseen","Vähintään {count} kirjainta vaaditaan automaattiseen täydentämiseen"], @@ -178,9 +176,6 @@ "No users found for {search}" : "Haulla {search} ei löytynyt käyttäjiä", "An error occurred (\"{message}\"). Please try again" : "Tapahtui virhe (\"{message}\"). Yritä uudestaan", "An error occurred. Please try again" : "Tapahtui virhe, yritä uudelleen", - "{sharee} (group)" : "{sharee} (ryhmä)", - "{sharee} (remote)" : "{sharee} (etä)", - "{sharee} (email)" : "{sharee} (sähköposti)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Jaa", "Name or email address..." : "Nimi tai sähköpostiosoite...", @@ -330,6 +325,9 @@ "Error setting expiration date" : "Virhe vanhenemispäivää asetettaessa", "The public link will expire no later than {days} days after it is created" : "Julkinen linkki vanhenee {days} päivän jälkeen sen luomisesta", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} jakoi linkillä", + "{sharee} (group)" : "{sharee} (ryhmä)", + "{sharee} (remote)" : "{sharee} (etä)", + "{sharee} (email)" : "{sharee} (sähköposti)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Jaa muille kirjoittamalla käyttäjä tai ryhmä, federoidun pilven tunniste tai sähköpostiosoite.", "Share with other people by entering a user or group or a federated cloud ID." : "Jaa muille kirjoittamalla käyttäjä, ryhmä tai federoidun pilven tunniste.", "Share with other people by entering a user or group or an email address." : "Jaa muille kirjoittamalla käyttäjä, ryhmä tai sähköpostiosoite.", @@ -359,6 +357,7 @@ "Back to log in" : "Palaa kirjautumiseen", "You are about to grant %s access to your %s account." : "Olet antamassa lupaa laitteelle %s päästä sinun %s tilille.", "Depending on your configuration, this button could also work to trust the domain:" : "Asetuksista riippuen, ylläpitäjänä saatat pystyä alla olevalla painikkeella lisäämään tämän verkkotunnuksen luotetuksi.", - "Copy URL" : "Kopioi osoite" + "Copy URL" : "Kopioi osoite", + "Enable" : "Ota käyttöön" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/core/l10n/fr.js b/core/l10n/fr.js index a0e31cc9e93..0378c04f7aa 100644 --- a/core/l10n/fr.js +++ b/core/l10n/fr.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Mode de maintenance activé", "Turned off maintenance mode" : "Mode de maintenance désactivé", "Maintenance mode is kept active" : "Le mode de maintenance est laissé actif", - "Waiting for cron to finish (checks again in 5 seconds) …" : "En attente que la tâche cron se termine (vérification dans 5 secondes)...", "Updating database schema" : "Mise à jour du schéma de la base de données", "Updated database" : "Base de données mise à jour", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Vérification de la possibilité de mettre à jour le schéma de la base de données (cela peut prendre un certain temps selon la taille de la base de données)", @@ -160,12 +159,13 @@ OC.L10N.register( "Choose a password for the public link" : "Choisissez un mot de passe pour le lien public", "Choose a password for the public link or press the \"Enter\" key" : "Choisissez un mot de passe pour le lien public ou appuyer sur \"Entrée\"", "Copied!" : "Copié !", + "Copy link" : "Copier le lien", "Not supported!" : "Non supporté!", "Press ⌘-C to copy." : "Appuyez sur ⌘-C pour copier.", "Press Ctrl-C to copy." : "Appuyez sur Ctrl-C pour copier.", + "Unable to create a link share" : "Impossible de créer un lien de partage", "Resharing is not allowed" : "Le repartage n'est pas autorisé", "Share to {name}" : "Partager avec {name}", - "Copy link" : "Copier le lien", "Link" : "Lien", "Password protect" : "Protéger par un mot de passe", "Allow editing" : "Permettre la modification", @@ -178,8 +178,13 @@ OC.L10N.register( "Expiration" : "Expiration", "Expiration date" : "Date d'expiration", "Note to recipient" : "Note au destinataire", + "Unshare" : "Ne plus partager", + "Delete share link" : "Supprimer le lien de partage", + "Add another link" : "Ajouter un autre lien", "Share link" : "Partager par lien public", - "Enable" : "Activer", + "New share link" : "Nouveau lien de partage", + "Password protect by Talk" : "Mot de passe protégé par Talk", + "Could not unshare" : "Impossible d'arrêter de partager", "Shared with you and the group {group} by {owner}" : "Partagé avec vous et le groupe {group} par {owner}", "Shared with you and {circle} by {owner}" : "Partagé avec vous et {circle} par {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Partagé avec vous et la conversation {conversation} par {owner}", @@ -192,16 +197,13 @@ OC.L10N.register( "email" : "Adresse de courriel", "conversation" : "conversation", "shared by {sharer}" : "partagé par {sharer}", - "Unshare" : "Ne plus partager", "Can reshare" : "Peut repartager", "Can edit" : "Peut éditer", "Can create" : "Peut créer", "Can change" : "Peut modifier", "Can delete" : "Peut supprimer", - "Password protect by Talk" : "Mot de passe protégé par Talk", "Access control" : "Contrôle d'accès", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} a partagé via un lien", - "Could not unshare" : "Impossible d'arrêter de partager", "Error while sharing" : "Erreur lors de la mise en partage", "Share details could not be loaded for this item." : "Les informations de partage n'ont pu être chargées pour cet élément.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Au moins {count} caractère est nécessaire pour l'autocomplétion","Au moins {count} caractères sont nécessaires pour l'autocomplétion"], @@ -210,12 +212,9 @@ OC.L10N.register( "No users found for {search}" : "Aucun utilisateur trouvé pour {search}", "An error occurred (\"{message}\"). Please try again" : "Une erreur est survenue (\"{message}\"). Veuillez réessayer", "An error occurred. Please try again" : "Une erreur est survenue. Merci de réessayer", - "{sharee} (group)" : "{sharee} (groupe)", - "{sharee} (remote)" : "{sharee} (distant)", "{sharee} (remote group)" : "{sharee} (groupe distant)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (discussion)", + "Other" : "Divers", "Share" : "Partager", "Name or email address..." : "Nom ou adresse mail...", "Name or federated cloud ID..." : "Nom ou ID du cloud fédéré...", @@ -301,6 +300,7 @@ OC.L10N.register( "Skip to main content" : "Passer au contenu principal", "Skip to navigation of app" : "Passer à la navigation d'application", "More apps" : "Plus d'applications", + "More" : "Plus", "More apps menu" : "Menu des autres applications", "Search" : "Rechercher", "Reset search" : "Réinitialiser la recherche", @@ -382,6 +382,9 @@ OC.L10N.register( "Error setting expiration date" : "Erreur lors de la configuration de la date d'expiration", "The public link will expire no later than {days} days after it is created" : "Ce lien public expirera dans {days} jours après sa création.", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} a partagé via un lien", + "{sharee} (group)" : "{sharee} (groupe)", + "{sharee} (remote)" : "{sharee} (distant)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Partager avec d'autres personnes en indiquant un nom d'utilisateur, un groupe, un identifiant de cloud fédéré ou une adresse email.", "Share with other people by entering a user or group or a federated cloud ID." : "Partager avec d'autres personnes en indiquant un utilisateur, un groupe ou un identifiant de cloud fédéré.", "Share with other people by entering a user or group or an email address." : "Partager avec d'autres personnes en indiquant un utilisateur, un groupe ou une adresse email.", @@ -413,6 +416,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Vous êtes sur le point d'accorder à \"%s\" l'accès à votre compte \"%s\".", "Depending on your configuration, this button could also work to trust the domain:" : "En fonction de votre configuration, ce bouton peut aussi fonctionner pour approuver ce domaine :", "Copy URL" : "Copier l'adresse URL", + "Enable" : "Activer", + "{sharee} (conversation)" : "{sharee} (discussion)", "Please log in before granting %s access to your %s account." : "Veuillez vous connecter avant d'autoriser %s à accéder à votre compte %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Vous trouverez d'autres informations sur la configuration dans la %sdocumentation %s." }, diff --git a/core/l10n/fr.json b/core/l10n/fr.json index 8aa4264d799..78052b136e8 100644 --- a/core/l10n/fr.json +++ b/core/l10n/fr.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Mode de maintenance activé", "Turned off maintenance mode" : "Mode de maintenance désactivé", "Maintenance mode is kept active" : "Le mode de maintenance est laissé actif", - "Waiting for cron to finish (checks again in 5 seconds) …" : "En attente que la tâche cron se termine (vérification dans 5 secondes)...", "Updating database schema" : "Mise à jour du schéma de la base de données", "Updated database" : "Base de données mise à jour", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Vérification de la possibilité de mettre à jour le schéma de la base de données (cela peut prendre un certain temps selon la taille de la base de données)", @@ -158,12 +157,13 @@ "Choose a password for the public link" : "Choisissez un mot de passe pour le lien public", "Choose a password for the public link or press the \"Enter\" key" : "Choisissez un mot de passe pour le lien public ou appuyer sur \"Entrée\"", "Copied!" : "Copié !", + "Copy link" : "Copier le lien", "Not supported!" : "Non supporté!", "Press ⌘-C to copy." : "Appuyez sur ⌘-C pour copier.", "Press Ctrl-C to copy." : "Appuyez sur Ctrl-C pour copier.", + "Unable to create a link share" : "Impossible de créer un lien de partage", "Resharing is not allowed" : "Le repartage n'est pas autorisé", "Share to {name}" : "Partager avec {name}", - "Copy link" : "Copier le lien", "Link" : "Lien", "Password protect" : "Protéger par un mot de passe", "Allow editing" : "Permettre la modification", @@ -176,8 +176,13 @@ "Expiration" : "Expiration", "Expiration date" : "Date d'expiration", "Note to recipient" : "Note au destinataire", + "Unshare" : "Ne plus partager", + "Delete share link" : "Supprimer le lien de partage", + "Add another link" : "Ajouter un autre lien", "Share link" : "Partager par lien public", - "Enable" : "Activer", + "New share link" : "Nouveau lien de partage", + "Password protect by Talk" : "Mot de passe protégé par Talk", + "Could not unshare" : "Impossible d'arrêter de partager", "Shared with you and the group {group} by {owner}" : "Partagé avec vous et le groupe {group} par {owner}", "Shared with you and {circle} by {owner}" : "Partagé avec vous et {circle} par {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Partagé avec vous et la conversation {conversation} par {owner}", @@ -190,16 +195,13 @@ "email" : "Adresse de courriel", "conversation" : "conversation", "shared by {sharer}" : "partagé par {sharer}", - "Unshare" : "Ne plus partager", "Can reshare" : "Peut repartager", "Can edit" : "Peut éditer", "Can create" : "Peut créer", "Can change" : "Peut modifier", "Can delete" : "Peut supprimer", - "Password protect by Talk" : "Mot de passe protégé par Talk", "Access control" : "Contrôle d'accès", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} a partagé via un lien", - "Could not unshare" : "Impossible d'arrêter de partager", "Error while sharing" : "Erreur lors de la mise en partage", "Share details could not be loaded for this item." : "Les informations de partage n'ont pu être chargées pour cet élément.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Au moins {count} caractère est nécessaire pour l'autocomplétion","Au moins {count} caractères sont nécessaires pour l'autocomplétion"], @@ -208,12 +210,9 @@ "No users found for {search}" : "Aucun utilisateur trouvé pour {search}", "An error occurred (\"{message}\"). Please try again" : "Une erreur est survenue (\"{message}\"). Veuillez réessayer", "An error occurred. Please try again" : "Une erreur est survenue. Merci de réessayer", - "{sharee} (group)" : "{sharee} (groupe)", - "{sharee} (remote)" : "{sharee} (distant)", "{sharee} (remote group)" : "{sharee} (groupe distant)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (discussion)", + "Other" : "Divers", "Share" : "Partager", "Name or email address..." : "Nom ou adresse mail...", "Name or federated cloud ID..." : "Nom ou ID du cloud fédéré...", @@ -299,6 +298,7 @@ "Skip to main content" : "Passer au contenu principal", "Skip to navigation of app" : "Passer à la navigation d'application", "More apps" : "Plus d'applications", + "More" : "Plus", "More apps menu" : "Menu des autres applications", "Search" : "Rechercher", "Reset search" : "Réinitialiser la recherche", @@ -380,6 +380,9 @@ "Error setting expiration date" : "Erreur lors de la configuration de la date d'expiration", "The public link will expire no later than {days} days after it is created" : "Ce lien public expirera dans {days} jours après sa création.", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} a partagé via un lien", + "{sharee} (group)" : "{sharee} (groupe)", + "{sharee} (remote)" : "{sharee} (distant)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Partager avec d'autres personnes en indiquant un nom d'utilisateur, un groupe, un identifiant de cloud fédéré ou une adresse email.", "Share with other people by entering a user or group or a federated cloud ID." : "Partager avec d'autres personnes en indiquant un utilisateur, un groupe ou un identifiant de cloud fédéré.", "Share with other people by entering a user or group or an email address." : "Partager avec d'autres personnes en indiquant un utilisateur, un groupe ou une adresse email.", @@ -411,6 +414,8 @@ "You are about to grant %s access to your %s account." : "Vous êtes sur le point d'accorder à \"%s\" l'accès à votre compte \"%s\".", "Depending on your configuration, this button could also work to trust the domain:" : "En fonction de votre configuration, ce bouton peut aussi fonctionner pour approuver ce domaine :", "Copy URL" : "Copier l'adresse URL", + "Enable" : "Activer", + "{sharee} (conversation)" : "{sharee} (discussion)", "Please log in before granting %s access to your %s account." : "Veuillez vous connecter avant d'autoriser %s à accéder à votre compte %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Vous trouverez d'autres informations sur la configuration dans la %sdocumentation %s." },"pluralForm" :"nplurals=2; plural=(n > 1);" diff --git a/core/l10n/he.js b/core/l10n/he.js index 06645532032..5370a4c00d1 100644 --- a/core/l10n/he.js +++ b/core/l10n/he.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "הפעלת מצב אחזקה", "Turned off maintenance mode" : "כיבוי מצב אחזקה", "Maintenance mode is kept active" : "מצב אחזקה נשמר פעיל", - "Waiting for cron to finish (checks again in 5 seconds) …" : "בהמתנה לסיום משימת ה־cron (תתבצע בדיקה עוד 5 שניות)…", "Updating database schema" : "עדכון סכימת מסד נתונים", "Updated database" : "עדכון מסד נתונים", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "בודק אם סכימת מסד הנתונים ניתנת לעדכון (פעולה זו יכולה להמשך זמן רב תלוי בגודל מסד הנתונים)", @@ -170,8 +169,10 @@ OC.L10N.register( "Set expiration date" : "הגדרת תאריך תפוגה", "Expiration" : "תפוגה", "Expiration date" : "תאריך התפוגה", + "Unshare" : "הסר שיתוף", "Share link" : "קישור לשיתוף", - "Enable" : "הפעלה", + "Password protect by Talk" : "הגנה בססמה על ידי Talk", + "Could not unshare" : "לא ניתן לבטל שיתוף", "Shared with you and the group {group} by {owner}" : "שותף אתך ועם הקבוצה {group} שבבעלות {owner}", "Shared with you by {owner}" : "שותף אתך על ידי {owner}", "Choose a password for the mail share" : "נא לבחור ססמה עבור השיתוף בדוא״ל", @@ -181,15 +182,12 @@ OC.L10N.register( "email" : "דוא״ל", "conversation" : "דיון", "shared by {sharer}" : "שותף ע״י {sharer}", - "Unshare" : "הסר שיתוף", "Can reshare" : "ניתן לשתף מחדש", "Can edit" : "ניתן לערוך", "Can create" : "ניתן ליצור", "Can change" : "ניתן לשנות", "Can delete" : "ניתן למחוק", - "Password protect by Talk" : "הגנה בססמה על ידי Talk", "Access control" : "בקרת גישה", - "Could not unshare" : "לא ניתן לבטל שיתוף", "Error while sharing" : "שגיאה במהלך השיתוף", "Share details could not be loaded for this item." : "לא ניתן היה לטעון מידע שיתוף לפריט זה", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["נדרש לפחות תו אחד להשלמה אוטומטית","נדרשים לפחות {count} תווים להשלמה אוטומטית","נדרשים לפחות {count} תווים להשלמה אוטומטית","נדרשים לפחות {count} תווים להשלמה אוטומטית"], @@ -198,12 +196,8 @@ OC.L10N.register( "No users found for {search}" : "לא אותרו משתמשים עבור {search}", "An error occurred (\"{message}\"). Please try again" : "אירעה שגיאה (\"{message}\"). נא לנסות שוב", "An error occurred. Please try again" : "אירעה שגיאה. יש לנסות שנית", - "{sharee} (group)" : "{sharee} (קבוצה)", - "{sharee} (remote)" : "{sharee} (מרוחק)", "{sharee} (remote group)" : "{sharee} (קבוצה מרוחקת)", - "{sharee} (email)" : "{sharee} (דוא״ל)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (דיון)", "Share" : "שתף", "Name or email address..." : "שם או כתובת דוא״ל…", "Name or federated cloud ID..." : "שם או מזהה ענן מאוגד…", @@ -359,6 +353,9 @@ OC.L10N.register( "Error setting expiration date" : "אירעה שגיאה בעת הגדרת תאריך התפוגה", "The public link will expire no later than {days} days after it is created" : "הקישור הציבורי יפוג עד {days} ימים לאחר שנוצר", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} שותף על ידי קישור", + "{sharee} (group)" : "{sharee} (קבוצה)", + "{sharee} (remote)" : "{sharee} (מרוחק)", + "{sharee} (email)" : "{sharee} (דוא״ל)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "ניתן לשתף אחרים על ידי הקלדת משתמש או קבוצה או מזהה ענן מאוגד או כתובת דוא״ל.", "Share with other people by entering a user or group or a federated cloud ID." : "ניתן לשתף אחרים על ידי הקלדת משתמש או קבוצה או מזהה ענן מאוגד.", "Share with other people by entering a user or group or an email address." : "ניתן לשתף עם אנשים אחרים על ידי הקלדת משתמש או קבוצה או כתובת דוא״ל.", @@ -389,6 +386,8 @@ OC.L10N.register( "Back to log in" : "חזרה לכניסה", "You are about to grant %s access to your %s account." : "פעולה זו תעניק הרשאת %s לחשבון שלך ב־%s.", "Depending on your configuration, this button could also work to trust the domain:" : "בהתאם לתצורה שלך, הכפתור הזה יכול לעבוד גם כדי לתת אמון בשם המתחם:", + "Enable" : "הפעלה", + "{sharee} (conversation)" : "{sharee} (דיון)", "Please log in before granting %s access to your %s account." : "נא להיכנס בטרם מתן הרשאת %s לחשבון שלך ב־%s.", "Further information how to configure this can be found in the %sdocumentation%s." : "ניתן למצוא מידע נוסף כיצד להגדיר ב%sתיעוד%s." }, diff --git a/core/l10n/he.json b/core/l10n/he.json index 10a4653e898..983ddbd2630 100644 --- a/core/l10n/he.json +++ b/core/l10n/he.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "הפעלת מצב אחזקה", "Turned off maintenance mode" : "כיבוי מצב אחזקה", "Maintenance mode is kept active" : "מצב אחזקה נשמר פעיל", - "Waiting for cron to finish (checks again in 5 seconds) …" : "בהמתנה לסיום משימת ה־cron (תתבצע בדיקה עוד 5 שניות)…", "Updating database schema" : "עדכון סכימת מסד נתונים", "Updated database" : "עדכון מסד נתונים", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "בודק אם סכימת מסד הנתונים ניתנת לעדכון (פעולה זו יכולה להמשך זמן רב תלוי בגודל מסד הנתונים)", @@ -168,8 +167,10 @@ "Set expiration date" : "הגדרת תאריך תפוגה", "Expiration" : "תפוגה", "Expiration date" : "תאריך התפוגה", + "Unshare" : "הסר שיתוף", "Share link" : "קישור לשיתוף", - "Enable" : "הפעלה", + "Password protect by Talk" : "הגנה בססמה על ידי Talk", + "Could not unshare" : "לא ניתן לבטל שיתוף", "Shared with you and the group {group} by {owner}" : "שותף אתך ועם הקבוצה {group} שבבעלות {owner}", "Shared with you by {owner}" : "שותף אתך על ידי {owner}", "Choose a password for the mail share" : "נא לבחור ססמה עבור השיתוף בדוא״ל", @@ -179,15 +180,12 @@ "email" : "דוא״ל", "conversation" : "דיון", "shared by {sharer}" : "שותף ע״י {sharer}", - "Unshare" : "הסר שיתוף", "Can reshare" : "ניתן לשתף מחדש", "Can edit" : "ניתן לערוך", "Can create" : "ניתן ליצור", "Can change" : "ניתן לשנות", "Can delete" : "ניתן למחוק", - "Password protect by Talk" : "הגנה בססמה על ידי Talk", "Access control" : "בקרת גישה", - "Could not unshare" : "לא ניתן לבטל שיתוף", "Error while sharing" : "שגיאה במהלך השיתוף", "Share details could not be loaded for this item." : "לא ניתן היה לטעון מידע שיתוף לפריט זה", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["נדרש לפחות תו אחד להשלמה אוטומטית","נדרשים לפחות {count} תווים להשלמה אוטומטית","נדרשים לפחות {count} תווים להשלמה אוטומטית","נדרשים לפחות {count} תווים להשלמה אוטומטית"], @@ -196,12 +194,8 @@ "No users found for {search}" : "לא אותרו משתמשים עבור {search}", "An error occurred (\"{message}\"). Please try again" : "אירעה שגיאה (\"{message}\"). נא לנסות שוב", "An error occurred. Please try again" : "אירעה שגיאה. יש לנסות שנית", - "{sharee} (group)" : "{sharee} (קבוצה)", - "{sharee} (remote)" : "{sharee} (מרוחק)", "{sharee} (remote group)" : "{sharee} (קבוצה מרוחקת)", - "{sharee} (email)" : "{sharee} (דוא״ל)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (דיון)", "Share" : "שתף", "Name or email address..." : "שם או כתובת דוא״ל…", "Name or federated cloud ID..." : "שם או מזהה ענן מאוגד…", @@ -357,6 +351,9 @@ "Error setting expiration date" : "אירעה שגיאה בעת הגדרת תאריך התפוגה", "The public link will expire no later than {days} days after it is created" : "הקישור הציבורי יפוג עד {days} ימים לאחר שנוצר", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} שותף על ידי קישור", + "{sharee} (group)" : "{sharee} (קבוצה)", + "{sharee} (remote)" : "{sharee} (מרוחק)", + "{sharee} (email)" : "{sharee} (דוא״ל)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "ניתן לשתף אחרים על ידי הקלדת משתמש או קבוצה או מזהה ענן מאוגד או כתובת דוא״ל.", "Share with other people by entering a user or group or a federated cloud ID." : "ניתן לשתף אחרים על ידי הקלדת משתמש או קבוצה או מזהה ענן מאוגד.", "Share with other people by entering a user or group or an email address." : "ניתן לשתף עם אנשים אחרים על ידי הקלדת משתמש או קבוצה או כתובת דוא״ל.", @@ -387,6 +384,8 @@ "Back to log in" : "חזרה לכניסה", "You are about to grant %s access to your %s account." : "פעולה זו תעניק הרשאת %s לחשבון שלך ב־%s.", "Depending on your configuration, this button could also work to trust the domain:" : "בהתאם לתצורה שלך, הכפתור הזה יכול לעבוד גם כדי לתת אמון בשם המתחם:", + "Enable" : "הפעלה", + "{sharee} (conversation)" : "{sharee} (דיון)", "Please log in before granting %s access to your %s account." : "נא להיכנס בטרם מתן הרשאת %s לחשבון שלך ב־%s.", "Further information how to configure this can be found in the %sdocumentation%s." : "ניתן למצוא מידע נוסף כיצד להגדיר ב%sתיעוד%s." },"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;" diff --git a/core/l10n/hr.js b/core/l10n/hr.js index 3bb802eee0a..d9fe5d40530 100644 --- a/core/l10n/hr.js +++ b/core/l10n/hr.js @@ -31,7 +31,6 @@ OC.L10N.register( "[%d / %d]: Checking table %s" : "[%d / %d]: Provjeravanje tablice %s", "Turned on maintenance mode" : "Način rada za održavanje uključen", "Turned off maintenance mode" : "Način rada za održavanje isključen", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Čekanje cron funkcije da završi (ponovna provjera za 5 sekundi) ...", "Updating database schema" : "Ažuriranje sheme baze podataka", "Updated database" : " Baza podataka ažurirana", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "U tijeku je provjeranje može li shema baza podataka biti ažurirana (ovo može potrajati ovisno o veličini baze podataka)", @@ -129,6 +128,7 @@ OC.L10N.register( "Set expiration date" : "Odredite datum isteka", "Expiration" : "Istjeće", "Expiration date" : "Datum isteka", + "Unshare" : "Prestanite dijeliti", "Share link" : "Podijelite vezu", "Shared with you and the group {group} by {owner}" : "Dijeljeno s vama i grupom {group} vlasnika {owner}", "Shared with you and {circle} by {owner}" : "Podijeljeno sa vama i {circle} od strane {owner}", @@ -136,7 +136,6 @@ OC.L10N.register( "group" : "Grupa", "remote" : "na daljinu", "email" : "e-pošta", - "Unshare" : "Prestanite dijeliti", "Can reshare" : "Ponovno dijeljenje omogućeno", "Can edit" : "Uređivanje omogućeno", "Can create" : "Stvaranje omogućeno", diff --git a/core/l10n/hr.json b/core/l10n/hr.json index e879b8031c5..2d15793dfe8 100644 --- a/core/l10n/hr.json +++ b/core/l10n/hr.json @@ -29,7 +29,6 @@ "[%d / %d]: Checking table %s" : "[%d / %d]: Provjeravanje tablice %s", "Turned on maintenance mode" : "Način rada za održavanje uključen", "Turned off maintenance mode" : "Način rada za održavanje isključen", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Čekanje cron funkcije da završi (ponovna provjera za 5 sekundi) ...", "Updating database schema" : "Ažuriranje sheme baze podataka", "Updated database" : " Baza podataka ažurirana", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "U tijeku je provjeranje može li shema baza podataka biti ažurirana (ovo može potrajati ovisno o veličini baze podataka)", @@ -127,6 +126,7 @@ "Set expiration date" : "Odredite datum isteka", "Expiration" : "Istjeće", "Expiration date" : "Datum isteka", + "Unshare" : "Prestanite dijeliti", "Share link" : "Podijelite vezu", "Shared with you and the group {group} by {owner}" : "Dijeljeno s vama i grupom {group} vlasnika {owner}", "Shared with you and {circle} by {owner}" : "Podijeljeno sa vama i {circle} od strane {owner}", @@ -134,7 +134,6 @@ "group" : "Grupa", "remote" : "na daljinu", "email" : "e-pošta", - "Unshare" : "Prestanite dijeliti", "Can reshare" : "Ponovno dijeljenje omogućeno", "Can edit" : "Uređivanje omogućeno", "Can create" : "Stvaranje omogućeno", diff --git a/core/l10n/hu.js b/core/l10n/hu.js index 6737eec4793..2e6a9e93e06 100644 --- a/core/l10n/hu.js +++ b/core/l10n/hu.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "A karbantartási mód bekapcsolva", "Turned off maintenance mode" : "A karbantartási mód kikapcsolva", "Maintenance mode is kept active" : "Karbantartási mód aktiválva maradt", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Várakozás az ütemezőre, hogy befejezze a műveletet (újra próbálkozás 5 másodperc múlva)...", "Updating database schema" : "Adatbázis séma frissítése", "Updated database" : "Adatbázis frissítve", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Annak ellenőrzése, hogy az adatbázis sémát lehet-e frissíteni (ez hosszabb ideig is eltarthat az adatbázis méretétől függően)", @@ -168,7 +167,9 @@ OC.L10N.register( "Set expiration date" : "Legyen lejárati idő", "Expiration" : "Lejárat", "Expiration date" : "Lejárati idő", + "Unshare" : "Megosztás visszavonása", "Share link" : "Megosztás hivatkozással", + "Could not unshare" : "Nem sikerült visszavonni a megosztást", "Shared with you and the group {group} by {owner}" : "{owner} megosztotta veled és ezzel a csoporttal: {group}", "Shared with you by {owner}" : "{owner} megosztotta veled", "Choose a password for the mail share" : "Válassz egy jelszót a levél megosztáshoz", @@ -178,14 +179,12 @@ OC.L10N.register( "email" : "e-mail", "conversation" : "beszélgetés", "shared by {sharer}" : "megosztotta: {sharer}", - "Unshare" : "Megosztás visszavonása", "Can reshare" : "Újra megoszthat", "Can edit" : "Szerkeszthet", "Can create" : "Létrehozhat", "Can change" : "Módosíthat", "Can delete" : "Törölhet", "Access control" : "Jogosultság kezelés", - "Could not unshare" : "Nem sikerült visszavonni a megosztást", "Error while sharing" : "Nem sikerült létrehozni a megosztást", "Share details could not be loaded for this item." : "A megosztás részletei nem lehet betölteni ehhez az elemhez.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Legalább {count} karakter szükséges az automatikus kiegészítéshez","Legalább {count} karakter szükséges az automatikus kiegészítéshez"], @@ -194,9 +193,6 @@ OC.L10N.register( "No users found for {search}" : "{search} keresésre nem található felhasználó", "An error occurred (\"{message}\"). Please try again" : "Hiba történt (\"{message}\"). Kérjük, próbálja meg újra! ", "An error occurred. Please try again" : "Hiba történt. Kérjük, próbálja meg újra!", - "{sharee} (group)" : "{sharee} (csoport)", - "{sharee} (remote)" : "{sharee} (távoli)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Megosztás", "Name or email address..." : "Név vagy e-mail cím...", @@ -350,6 +346,9 @@ OC.L10N.register( "Error setting expiration date" : "Nem sikerült a lejárati időt beállítani", "The public link will expire no later than {days} days after it is created" : "A nyilvános hivatkozás érvényessége legkorábban {days} nappal a létrehozása után jár csak le", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} megosztva hivatkozással", + "{sharee} (group)" : "{sharee} (csoport)", + "{sharee} (remote)" : "{sharee} (távoli)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Megosztás más emberekkel név vagy csoport, egy egységes felhőazonosító vagy e-mail cím megadásával.", "Share with other people by entering a user or group or a federated cloud ID." : "Megosztás más emberekkel felhasználó, csoport vagy egyesített felhőazonosító megadásával.", "Share with other people by entering a user or group or an email address." : "Megosztás más emberekkel név, csoport vagy e-mail cím megadásával.", diff --git a/core/l10n/hu.json b/core/l10n/hu.json index c4644231513..91cf6ada765 100644 --- a/core/l10n/hu.json +++ b/core/l10n/hu.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "A karbantartási mód bekapcsolva", "Turned off maintenance mode" : "A karbantartási mód kikapcsolva", "Maintenance mode is kept active" : "Karbantartási mód aktiválva maradt", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Várakozás az ütemezőre, hogy befejezze a műveletet (újra próbálkozás 5 másodperc múlva)...", "Updating database schema" : "Adatbázis séma frissítése", "Updated database" : "Adatbázis frissítve", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Annak ellenőrzése, hogy az adatbázis sémát lehet-e frissíteni (ez hosszabb ideig is eltarthat az adatbázis méretétől függően)", @@ -166,7 +165,9 @@ "Set expiration date" : "Legyen lejárati idő", "Expiration" : "Lejárat", "Expiration date" : "Lejárati idő", + "Unshare" : "Megosztás visszavonása", "Share link" : "Megosztás hivatkozással", + "Could not unshare" : "Nem sikerült visszavonni a megosztást", "Shared with you and the group {group} by {owner}" : "{owner} megosztotta veled és ezzel a csoporttal: {group}", "Shared with you by {owner}" : "{owner} megosztotta veled", "Choose a password for the mail share" : "Válassz egy jelszót a levél megosztáshoz", @@ -176,14 +177,12 @@ "email" : "e-mail", "conversation" : "beszélgetés", "shared by {sharer}" : "megosztotta: {sharer}", - "Unshare" : "Megosztás visszavonása", "Can reshare" : "Újra megoszthat", "Can edit" : "Szerkeszthet", "Can create" : "Létrehozhat", "Can change" : "Módosíthat", "Can delete" : "Törölhet", "Access control" : "Jogosultság kezelés", - "Could not unshare" : "Nem sikerült visszavonni a megosztást", "Error while sharing" : "Nem sikerült létrehozni a megosztást", "Share details could not be loaded for this item." : "A megosztás részletei nem lehet betölteni ehhez az elemhez.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Legalább {count} karakter szükséges az automatikus kiegészítéshez","Legalább {count} karakter szükséges az automatikus kiegészítéshez"], @@ -192,9 +191,6 @@ "No users found for {search}" : "{search} keresésre nem található felhasználó", "An error occurred (\"{message}\"). Please try again" : "Hiba történt (\"{message}\"). Kérjük, próbálja meg újra! ", "An error occurred. Please try again" : "Hiba történt. Kérjük, próbálja meg újra!", - "{sharee} (group)" : "{sharee} (csoport)", - "{sharee} (remote)" : "{sharee} (távoli)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Megosztás", "Name or email address..." : "Név vagy e-mail cím...", @@ -348,6 +344,9 @@ "Error setting expiration date" : "Nem sikerült a lejárati időt beállítani", "The public link will expire no later than {days} days after it is created" : "A nyilvános hivatkozás érvényessége legkorábban {days} nappal a létrehozása után jár csak le", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} megosztva hivatkozással", + "{sharee} (group)" : "{sharee} (csoport)", + "{sharee} (remote)" : "{sharee} (távoli)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Megosztás más emberekkel név vagy csoport, egy egységes felhőazonosító vagy e-mail cím megadásával.", "Share with other people by entering a user or group or a federated cloud ID." : "Megosztás más emberekkel felhasználó, csoport vagy egyesített felhőazonosító megadásával.", "Share with other people by entering a user or group or an email address." : "Megosztás más emberekkel név, csoport vagy e-mail cím megadásával.", diff --git a/core/l10n/id.js b/core/l10n/id.js index 66ac2c6cc56..a5a3106ff4a 100644 --- a/core/l10n/id.js +++ b/core/l10n/id.js @@ -104,14 +104,14 @@ OC.L10N.register( "Set expiration date" : "Atur tanggal kedaluwarsa", "Expiration" : "Kedaluwarsa", "Expiration date" : "Tanggal kedaluwarsa", + "Unshare" : "Batalkan berbagi", "Share link" : "Bagikan tautan", + "Could not unshare" : "Tidak dapat membatalkan pembagian", "Shared with you and the group {group} by {owner}" : "Dibagikan dengan anda dan grup {group} oleh {owner}", "Shared with you by {owner}" : "Dibagikan dengan anda oleh {owner}", "group" : "grup", "remote" : "remote", "email" : "surel", - "Unshare" : "Batalkan berbagi", - "Could not unshare" : "Tidak dapat membatalkan pembagian", "Error while sharing" : "Kesalahan saat membagikan", "Share details could not be loaded for this item." : "Rincian berbagi tidak dapat dimuat untuk item ini.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Sekurangnya {count} karakter dibutuhkan untuk autocompletion"], @@ -119,9 +119,6 @@ OC.L10N.register( "No users or groups found for {search}" : "Tidak ada pengguna atau grup ditemukan untuk {search}", "No users found for {search}" : "Tidak ada pengguna ditemukan untuk {search}", "An error occurred. Please try again" : "Terjadi kesalahan. Silakan coba lagi", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (remote)", - "{sharee} (email)" : "{sharee} (surel)", "Share" : "Bagikan", "Error" : "Kesalahan", "Error removing share" : "Terjadi kesalahan saat menghapus pembagian", @@ -222,6 +219,9 @@ OC.L10N.register( "Error setting expiration date" : "Kesalahan saat mengatur tanggal kedaluwarsa", "The public link will expire no later than {days} days after it is created" : "Tautan publik akan kadaluarsa tidak lebih dari {days} hari setelah ini dibuat", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} dibagikan lewat tautan", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (surel)", "The specified document has not been found on the server." : "Dokumen yang diminta tidak tersedia pada server.", "You can click here to return to %s." : "Anda dapat klik disini unutk kembali ke %s.", "Stay logged in" : "Tetap masuk", diff --git a/core/l10n/id.json b/core/l10n/id.json index 3fb08a344a2..dc28b38631e 100644 --- a/core/l10n/id.json +++ b/core/l10n/id.json @@ -102,14 +102,14 @@ "Set expiration date" : "Atur tanggal kedaluwarsa", "Expiration" : "Kedaluwarsa", "Expiration date" : "Tanggal kedaluwarsa", + "Unshare" : "Batalkan berbagi", "Share link" : "Bagikan tautan", + "Could not unshare" : "Tidak dapat membatalkan pembagian", "Shared with you and the group {group} by {owner}" : "Dibagikan dengan anda dan grup {group} oleh {owner}", "Shared with you by {owner}" : "Dibagikan dengan anda oleh {owner}", "group" : "grup", "remote" : "remote", "email" : "surel", - "Unshare" : "Batalkan berbagi", - "Could not unshare" : "Tidak dapat membatalkan pembagian", "Error while sharing" : "Kesalahan saat membagikan", "Share details could not be loaded for this item." : "Rincian berbagi tidak dapat dimuat untuk item ini.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Sekurangnya {count} karakter dibutuhkan untuk autocompletion"], @@ -117,9 +117,6 @@ "No users or groups found for {search}" : "Tidak ada pengguna atau grup ditemukan untuk {search}", "No users found for {search}" : "Tidak ada pengguna ditemukan untuk {search}", "An error occurred. Please try again" : "Terjadi kesalahan. Silakan coba lagi", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (remote)", - "{sharee} (email)" : "{sharee} (surel)", "Share" : "Bagikan", "Error" : "Kesalahan", "Error removing share" : "Terjadi kesalahan saat menghapus pembagian", @@ -220,6 +217,9 @@ "Error setting expiration date" : "Kesalahan saat mengatur tanggal kedaluwarsa", "The public link will expire no later than {days} days after it is created" : "Tautan publik akan kadaluarsa tidak lebih dari {days} hari setelah ini dibuat", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} dibagikan lewat tautan", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (surel)", "The specified document has not been found on the server." : "Dokumen yang diminta tidak tersedia pada server.", "You can click here to return to %s." : "Anda dapat klik disini unutk kembali ke %s.", "Stay logged in" : "Tetap masuk", diff --git a/core/l10n/is.js b/core/l10n/is.js index ee23b177fc0..3164cdc881c 100644 --- a/core/l10n/is.js +++ b/core/l10n/is.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Kveikt á viðhaldsham", "Turned off maintenance mode" : "Slökkt á viðhaldsham", "Maintenance mode is kept active" : "Viðhaldsham er haldið virkum", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Bíð þess að cron ljúki vinnslu (athugaðu aftur eftir 5 sekúndur) …", "Updating database schema" : "Uppfæri gagnagrunnsskema", "Updated database" : "Uppfærði gagnagrunn", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Athuga hvort hægt sé að uppfæra gagnagrunnsskema (þetta getur tekið langan tíma ef gagnagrunnurinn er mjög stór)", @@ -155,12 +154,12 @@ OC.L10N.register( "Choose a password for the public link" : "Veldu þér lykilorð fyrir almenningstengil", "Choose a password for the public link or press the \"Enter\" key" : "Veldu þér lykilorð fyrir opinbera tengilinn eða ýttu á \"Ente\" lykilinn", "Copied!" : "Afritað!", + "Copy link" : "Afrita tengil", "Not supported!" : "Óstutt!", "Press ⌘-C to copy." : "Ýttu á ⌘-C til að afrita.", "Press Ctrl-C to copy." : "Ýttu á Ctrl-C til að afrita.", "Resharing is not allowed" : "Endurdeiling er ekki leyfð", "Share to {name}" : "Deila til {name}", - "Copy link" : "Afrita tengil", "Link" : "Tengill", "Password protect" : "Verja með lykilorði", "Allow editing" : "Leyfa breytingar", @@ -173,8 +172,10 @@ OC.L10N.register( "Expiration" : "Rennur út", "Expiration date" : "Gildir til", "Note to recipient" : "Minnispunktur til viðtakanda", + "Unshare" : "Hætta deilingu", "Share link" : "Deila tengli", - "Enable" : "Virkja", + "Password protect by Talk" : "Verja með lykilorði í gegnum Talk", + "Could not unshare" : "Gat ekki hætt deilingu", "Shared with you and the group {group} by {owner}" : "Deilt með þér og hópnum {group} af {owner}", "Shared with you and {circle} by {owner}" : "Deilt með þér og {circle} af {owner}", "Shared with you in a conversation by {owner}" : "Deilt með þér í samtali af {owner}", @@ -186,7 +187,6 @@ OC.L10N.register( "email" : "tölvupóstur", "conversation" : "samtal", "shared by {sharer}" : "deilt af {sharer}", - "Unshare" : "Hætta deilingu", "Can reshare" : "Getur endurdeilt", "Can edit" : "Getur breytt", "Can create" : "Getur búið til", @@ -194,7 +194,6 @@ OC.L10N.register( "Can delete" : "Getur eytt", "Access control" : "Aðgangsstýring", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} deildi með tengli", - "Could not unshare" : "Gat ekki hætt deilingu", "Error while sharing" : "Villa við deilingu", "Share details could not be loaded for this item." : "Ekki tókst að hlaða inn upplýsingum um sameign varðandi þetta atriði.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Það þarf a.m.k. {count} staf til að sjálfvirk útfylling virki","Það þarf a.m.k. {count} stafi til að sjálfvirk útfylling virki"], @@ -203,12 +202,8 @@ OC.L10N.register( "No users found for {search}" : "Engir notendur fundust með {search}", "An error occurred (\"{message}\"). Please try again" : "Villa kom upp (\"{message}\"). Endilega reyndu aftur", "An error occurred. Please try again" : "Villa kom upp. Endilega reyndu aftur", - "{sharee} (group)" : "{sharee} (hópur)", - "{sharee} (remote)" : "{sharee} (fjartengdur)", "{sharee} (remote group)" : "{sharee} (fjartengdur hópur)", - "{sharee} (email)" : "{sharee} (tölvupóstur)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (samtal)", "Share" : "Deila", "Name or email address..." : "Nafn eða tölvupóstfang...", "Name or federated cloud ID..." : "Nafn eða skýjasambandsauðkenni (Federated Cloud ID)...", @@ -291,6 +286,7 @@ OC.L10N.register( "See the documentation" : "Sjá hjálparskjölin", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Þetta forrit krefst JavaScript fyrir rétta virkni. {linkstart} virkjaðu JavaScript {linkend} og endurlestu síðan síðuna.", "Skip to main content" : "Sleppa og fara í meginefni", + "Skip to navigation of app" : "Hlaupa yfir í flakk innan forrits", "More apps" : "Fleiri forrit", "More apps menu" : "Valmynd með fleiri forrit", "Search" : "Leita", @@ -370,6 +366,9 @@ OC.L10N.register( "Error setting expiration date" : "Villa við að setja gildistíma", "The public link will expire no later than {days} days after it is created" : "Almenningstengillinn rennur út eigi síðar en {days} dögum eftir að hann er útbúinn", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} deildi með tengli", + "{sharee} (group)" : "{sharee} (hópur)", + "{sharee} (remote)" : "{sharee} (fjartengdur)", + "{sharee} (email)" : "{sharee} (tölvupóstur)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Deildu með öðru fólki með því að setja inn notanda, hóp, skýjasambandsauðkenni eða tölvupóstfang.", "Share with other people by entering a user or group or a federated cloud ID." : "Deildu með öðru fólki með því að setja inn notanda, hóp eða skýjasambandsauðkenni.", "Share with other people by entering a user or group or an email address." : "Deildu með öðru fólki með því að setja inn notanda, hóp eða tölvupóstfang.", @@ -401,6 +400,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Þú ert að fara að leyfa %s aðgang að %s notandaaðgangnum þínum.", "Depending on your configuration, this button could also work to trust the domain:" : "Það fer eftir stillingunum þínum, þessi hnappur gæti einnig virkað til að treysta þessu léni.", "Copy URL" : "Afrita slóð", + "Enable" : "Virkja", + "{sharee} (conversation)" : "{sharee} (samtal)", "Please log in before granting %s access to your %s account." : "Skráði þig inn áður en þú leyfir %s aðgang að %s notandaaðgangnum þínum.", "Further information how to configure this can be found in the %sdocumentation%s." : "Frekari upplýsingar um hvernig hægt er að stilla þetta má finna í %shjálparskjölunum%s." }, diff --git a/core/l10n/is.json b/core/l10n/is.json index bde6d1045ab..53cafdd0f3d 100644 --- a/core/l10n/is.json +++ b/core/l10n/is.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Kveikt á viðhaldsham", "Turned off maintenance mode" : "Slökkt á viðhaldsham", "Maintenance mode is kept active" : "Viðhaldsham er haldið virkum", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Bíð þess að cron ljúki vinnslu (athugaðu aftur eftir 5 sekúndur) …", "Updating database schema" : "Uppfæri gagnagrunnsskema", "Updated database" : "Uppfærði gagnagrunn", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Athuga hvort hægt sé að uppfæra gagnagrunnsskema (þetta getur tekið langan tíma ef gagnagrunnurinn er mjög stór)", @@ -153,12 +152,12 @@ "Choose a password for the public link" : "Veldu þér lykilorð fyrir almenningstengil", "Choose a password for the public link or press the \"Enter\" key" : "Veldu þér lykilorð fyrir opinbera tengilinn eða ýttu á \"Ente\" lykilinn", "Copied!" : "Afritað!", + "Copy link" : "Afrita tengil", "Not supported!" : "Óstutt!", "Press ⌘-C to copy." : "Ýttu á ⌘-C til að afrita.", "Press Ctrl-C to copy." : "Ýttu á Ctrl-C til að afrita.", "Resharing is not allowed" : "Endurdeiling er ekki leyfð", "Share to {name}" : "Deila til {name}", - "Copy link" : "Afrita tengil", "Link" : "Tengill", "Password protect" : "Verja með lykilorði", "Allow editing" : "Leyfa breytingar", @@ -171,8 +170,10 @@ "Expiration" : "Rennur út", "Expiration date" : "Gildir til", "Note to recipient" : "Minnispunktur til viðtakanda", + "Unshare" : "Hætta deilingu", "Share link" : "Deila tengli", - "Enable" : "Virkja", + "Password protect by Talk" : "Verja með lykilorði í gegnum Talk", + "Could not unshare" : "Gat ekki hætt deilingu", "Shared with you and the group {group} by {owner}" : "Deilt með þér og hópnum {group} af {owner}", "Shared with you and {circle} by {owner}" : "Deilt með þér og {circle} af {owner}", "Shared with you in a conversation by {owner}" : "Deilt með þér í samtali af {owner}", @@ -184,7 +185,6 @@ "email" : "tölvupóstur", "conversation" : "samtal", "shared by {sharer}" : "deilt af {sharer}", - "Unshare" : "Hætta deilingu", "Can reshare" : "Getur endurdeilt", "Can edit" : "Getur breytt", "Can create" : "Getur búið til", @@ -192,7 +192,6 @@ "Can delete" : "Getur eytt", "Access control" : "Aðgangsstýring", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} deildi með tengli", - "Could not unshare" : "Gat ekki hætt deilingu", "Error while sharing" : "Villa við deilingu", "Share details could not be loaded for this item." : "Ekki tókst að hlaða inn upplýsingum um sameign varðandi þetta atriði.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Það þarf a.m.k. {count} staf til að sjálfvirk útfylling virki","Það þarf a.m.k. {count} stafi til að sjálfvirk útfylling virki"], @@ -201,12 +200,8 @@ "No users found for {search}" : "Engir notendur fundust með {search}", "An error occurred (\"{message}\"). Please try again" : "Villa kom upp (\"{message}\"). Endilega reyndu aftur", "An error occurred. Please try again" : "Villa kom upp. Endilega reyndu aftur", - "{sharee} (group)" : "{sharee} (hópur)", - "{sharee} (remote)" : "{sharee} (fjartengdur)", "{sharee} (remote group)" : "{sharee} (fjartengdur hópur)", - "{sharee} (email)" : "{sharee} (tölvupóstur)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (samtal)", "Share" : "Deila", "Name or email address..." : "Nafn eða tölvupóstfang...", "Name or federated cloud ID..." : "Nafn eða skýjasambandsauðkenni (Federated Cloud ID)...", @@ -289,6 +284,7 @@ "See the documentation" : "Sjá hjálparskjölin", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Þetta forrit krefst JavaScript fyrir rétta virkni. {linkstart} virkjaðu JavaScript {linkend} og endurlestu síðan síðuna.", "Skip to main content" : "Sleppa og fara í meginefni", + "Skip to navigation of app" : "Hlaupa yfir í flakk innan forrits", "More apps" : "Fleiri forrit", "More apps menu" : "Valmynd með fleiri forrit", "Search" : "Leita", @@ -368,6 +364,9 @@ "Error setting expiration date" : "Villa við að setja gildistíma", "The public link will expire no later than {days} days after it is created" : "Almenningstengillinn rennur út eigi síðar en {days} dögum eftir að hann er útbúinn", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} deildi með tengli", + "{sharee} (group)" : "{sharee} (hópur)", + "{sharee} (remote)" : "{sharee} (fjartengdur)", + "{sharee} (email)" : "{sharee} (tölvupóstur)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Deildu með öðru fólki með því að setja inn notanda, hóp, skýjasambandsauðkenni eða tölvupóstfang.", "Share with other people by entering a user or group or a federated cloud ID." : "Deildu með öðru fólki með því að setja inn notanda, hóp eða skýjasambandsauðkenni.", "Share with other people by entering a user or group or an email address." : "Deildu með öðru fólki með því að setja inn notanda, hóp eða tölvupóstfang.", @@ -399,6 +398,8 @@ "You are about to grant %s access to your %s account." : "Þú ert að fara að leyfa %s aðgang að %s notandaaðgangnum þínum.", "Depending on your configuration, this button could also work to trust the domain:" : "Það fer eftir stillingunum þínum, þessi hnappur gæti einnig virkað til að treysta þessu léni.", "Copy URL" : "Afrita slóð", + "Enable" : "Virkja", + "{sharee} (conversation)" : "{sharee} (samtal)", "Please log in before granting %s access to your %s account." : "Skráði þig inn áður en þú leyfir %s aðgang að %s notandaaðgangnum þínum.", "Further information how to configure this can be found in the %sdocumentation%s." : "Frekari upplýsingar um hvernig hægt er að stilla þetta má finna í %shjálparskjölunum%s." },"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);" diff --git a/core/l10n/it.js b/core/l10n/it.js index 28682cb778c..4eae6f30eab 100644 --- a/core/l10n/it.js +++ b/core/l10n/it.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Modalità di manutenzione attivata", "Turned off maintenance mode" : "Modalità di manutenzione disattivata", "Maintenance mode is kept active" : "La modalità di manutenzione è lasciata attiva", - "Waiting for cron to finish (checks again in 5 seconds) …" : "In attesa che cron finisca (nuovo controllo tra 5 secondi)…", "Updating database schema" : "Aggiornamento schema database", "Updated database" : "Database aggiornato", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Controllo che lo schema del database possa essere aggiornato (ciò potrebbe richiedere molto tempo in base alla dimensione del database)", @@ -160,13 +159,14 @@ OC.L10N.register( "Choose a password for the public link" : "Scegli una password per il collegamento pubblico", "Choose a password for the public link or press the \"Enter\" key" : "Scegli una password per il collegamento pubblico o premi il tasto \"Invio\"", "Copied!" : "Copiati!", + "Copy link" : "Copia collegamento", "Not supported!" : "Non supportato!", "Press ⌘-C to copy." : "Premi ⌘-C per copiare.", "Press Ctrl-C to copy." : "Premi Ctrl-C per copiare.", "Resharing is not allowed" : "La ri-condivisione non è consentita", "Share to {name}" : "Condividi con {name}", - "Copy link" : "Copia collegamento", "Link" : "Collegamento", + "Hide download" : "Nascondi scaricamento", "Password protect" : "Proteggi con password", "Allow editing" : "Consenti la modifica", "Email link to person" : "Invia collegamento via email", @@ -178,8 +178,10 @@ OC.L10N.register( "Expiration" : "Scadenza", "Expiration date" : "Data di scadenza", "Note to recipient" : "Nota per destinatario", + "Unshare" : "Rimuovi condivisione", "Share link" : "Condividi collegamento", - "Enable" : "Abilita", + "Password protect by Talk" : "Protezione con password di Talk", + "Could not unshare" : "Impossibile rimuovere la condivisione", "Shared with you and the group {group} by {owner}" : "Condiviso con te e con il gruppo {group} da {owner}", "Shared with you and {circle} by {owner}" : "Condiviso con te e {circle} da {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Condiviso con te e con la conversazione {conversation} da {owner}", @@ -192,16 +194,13 @@ OC.L10N.register( "email" : "email", "conversation" : "conversazione", "shared by {sharer}" : "condiviso da {sharer}", - "Unshare" : "Rimuovi condivisione", "Can reshare" : "Può ri-condividere", "Can edit" : "Può modificare", "Can create" : "Può creare", "Can change" : "Può cambiare", "Can delete" : "Può eliminare", - "Password protect by Talk" : "Protezione con password di Talk", "Access control" : "Controllo d'accesso", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} ha condiviso tramite collegamento", - "Could not unshare" : "Impossibile rimuovere la condivisione", "Error while sharing" : "Errore durante la condivisione", "Share details could not be loaded for this item." : "I dettagli della condivisione non possono essere caricati per questo elemento.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Almeno {count} carattere è richiesto per l'autocompletamento","Almeno {count} caratteri sono richiesti per il completamento automatico"], @@ -210,12 +209,10 @@ OC.L10N.register( "No users found for {search}" : "Nessun utente trovato per {search}", "An error occurred (\"{message}\"). Please try again" : "Si è verificato un errore (\"{message}\"). Prova ancora", "An error occurred. Please try again" : "Si è verificato un errore. Prova ancora", - "{sharee} (group)" : "{sharee} (group)", - "{sharee} (remote)" : "{sharee} (remote)", "{sharee} (remote group)" : "{sharee} (remote group)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Home", + "Other" : "Altro", "Share" : "Condividi", "Name or email address..." : "Nome o indirizzo email...", "Name or federated cloud ID..." : "Nome o ID di cloud federata...", @@ -301,6 +298,7 @@ OC.L10N.register( "Skip to main content" : "Passa al contenuto principale", "Skip to navigation of app" : "Passa alla navigazione dell'applicazione", "More apps" : "Altre applicazioni", + "More" : "Altro", "More apps menu" : "Menu delle altre applicazioni", "Search" : "Cerca", "Reset search" : "Ripristina ricerca", @@ -382,6 +380,9 @@ OC.L10N.register( "Error setting expiration date" : "Errore durante l'impostazione della data di scadenza", "The public link will expire no later than {days} days after it is created" : "Il collegamento pubblico scadrà non più tardi di {days} giorni dopo la sua creazione", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha condiviso tramite collegamento", + "{sharee} (group)" : "{sharee} (group)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Condividi con altre persone digitando un utente o un gruppo, un ID di cloud federata o un indirizzo di posta elettronica.", "Share with other people by entering a user or group or a federated cloud ID." : "Condividi con altre persone digitando un utente, un gruppo o un ID di cloud federata.", "Share with other people by entering a user or group or an email address." : "Condividi con altre persone digitando un utente, un gruppo o un indirizzo di posta elettronica.", @@ -413,6 +414,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Stai per accordare a \"%s\" l'accesso al tuo account %s.", "Depending on your configuration, this button could also work to trust the domain:" : "In base alla tua configurazione, questo pulsante può funzionare anche per rendere attendibile il dominio:", "Copy URL" : "Copia URL", + "Enable" : "Abilita", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Accedi prima di accordare a %s l'accesso al tuo account %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Ulteriori informazioni sulla configurazione sono disponibili nella %sdocumentazione%s." }, diff --git a/core/l10n/it.json b/core/l10n/it.json index 129e9471b69..9bba335ee2f 100644 --- a/core/l10n/it.json +++ b/core/l10n/it.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Modalità di manutenzione attivata", "Turned off maintenance mode" : "Modalità di manutenzione disattivata", "Maintenance mode is kept active" : "La modalità di manutenzione è lasciata attiva", - "Waiting for cron to finish (checks again in 5 seconds) …" : "In attesa che cron finisca (nuovo controllo tra 5 secondi)…", "Updating database schema" : "Aggiornamento schema database", "Updated database" : "Database aggiornato", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Controllo che lo schema del database possa essere aggiornato (ciò potrebbe richiedere molto tempo in base alla dimensione del database)", @@ -158,13 +157,14 @@ "Choose a password for the public link" : "Scegli una password per il collegamento pubblico", "Choose a password for the public link or press the \"Enter\" key" : "Scegli una password per il collegamento pubblico o premi il tasto \"Invio\"", "Copied!" : "Copiati!", + "Copy link" : "Copia collegamento", "Not supported!" : "Non supportato!", "Press ⌘-C to copy." : "Premi ⌘-C per copiare.", "Press Ctrl-C to copy." : "Premi Ctrl-C per copiare.", "Resharing is not allowed" : "La ri-condivisione non è consentita", "Share to {name}" : "Condividi con {name}", - "Copy link" : "Copia collegamento", "Link" : "Collegamento", + "Hide download" : "Nascondi scaricamento", "Password protect" : "Proteggi con password", "Allow editing" : "Consenti la modifica", "Email link to person" : "Invia collegamento via email", @@ -176,8 +176,10 @@ "Expiration" : "Scadenza", "Expiration date" : "Data di scadenza", "Note to recipient" : "Nota per destinatario", + "Unshare" : "Rimuovi condivisione", "Share link" : "Condividi collegamento", - "Enable" : "Abilita", + "Password protect by Talk" : "Protezione con password di Talk", + "Could not unshare" : "Impossibile rimuovere la condivisione", "Shared with you and the group {group} by {owner}" : "Condiviso con te e con il gruppo {group} da {owner}", "Shared with you and {circle} by {owner}" : "Condiviso con te e {circle} da {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Condiviso con te e con la conversazione {conversation} da {owner}", @@ -190,16 +192,13 @@ "email" : "email", "conversation" : "conversazione", "shared by {sharer}" : "condiviso da {sharer}", - "Unshare" : "Rimuovi condivisione", "Can reshare" : "Può ri-condividere", "Can edit" : "Può modificare", "Can create" : "Può creare", "Can change" : "Può cambiare", "Can delete" : "Può eliminare", - "Password protect by Talk" : "Protezione con password di Talk", "Access control" : "Controllo d'accesso", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} ha condiviso tramite collegamento", - "Could not unshare" : "Impossibile rimuovere la condivisione", "Error while sharing" : "Errore durante la condivisione", "Share details could not be loaded for this item." : "I dettagli della condivisione non possono essere caricati per questo elemento.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Almeno {count} carattere è richiesto per l'autocompletamento","Almeno {count} caratteri sono richiesti per il completamento automatico"], @@ -208,12 +207,10 @@ "No users found for {search}" : "Nessun utente trovato per {search}", "An error occurred (\"{message}\"). Please try again" : "Si è verificato un errore (\"{message}\"). Prova ancora", "An error occurred. Please try again" : "Si è verificato un errore. Prova ancora", - "{sharee} (group)" : "{sharee} (group)", - "{sharee} (remote)" : "{sharee} (remote)", "{sharee} (remote group)" : "{sharee} (remote group)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Home", + "Other" : "Altro", "Share" : "Condividi", "Name or email address..." : "Nome o indirizzo email...", "Name or federated cloud ID..." : "Nome o ID di cloud federata...", @@ -299,6 +296,7 @@ "Skip to main content" : "Passa al contenuto principale", "Skip to navigation of app" : "Passa alla navigazione dell'applicazione", "More apps" : "Altre applicazioni", + "More" : "Altro", "More apps menu" : "Menu delle altre applicazioni", "Search" : "Cerca", "Reset search" : "Ripristina ricerca", @@ -380,6 +378,9 @@ "Error setting expiration date" : "Errore durante l'impostazione della data di scadenza", "The public link will expire no later than {days} days after it is created" : "Il collegamento pubblico scadrà non più tardi di {days} giorni dopo la sua creazione", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha condiviso tramite collegamento", + "{sharee} (group)" : "{sharee} (group)", + "{sharee} (remote)" : "{sharee} (remote)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Condividi con altre persone digitando un utente o un gruppo, un ID di cloud federata o un indirizzo di posta elettronica.", "Share with other people by entering a user or group or a federated cloud ID." : "Condividi con altre persone digitando un utente, un gruppo o un ID di cloud federata.", "Share with other people by entering a user or group or an email address." : "Condividi con altre persone digitando un utente, un gruppo o un indirizzo di posta elettronica.", @@ -411,6 +412,8 @@ "You are about to grant %s access to your %s account." : "Stai per accordare a \"%s\" l'accesso al tuo account %s.", "Depending on your configuration, this button could also work to trust the domain:" : "In base alla tua configurazione, questo pulsante può funzionare anche per rendere attendibile il dominio:", "Copy URL" : "Copia URL", + "Enable" : "Abilita", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Accedi prima di accordare a %s l'accesso al tuo account %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Ulteriori informazioni sulla configurazione sono disponibili nella %sdocumentazione%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/ja.js b/core/l10n/ja.js index c3eb3db054e..4846686d5b3 100644 --- a/core/l10n/ja.js +++ b/core/l10n/ja.js @@ -132,7 +132,9 @@ OC.L10N.register( "Set expiration date" : "有効期限を設定", "Expiration" : "期限切れ", "Expiration date" : "有効期限", + "Unshare" : "共有解除", "Share link" : "URLで共有", + "Could not unshare" : "共有の解除ができませんでした", "Shared with you and the group {group} by {owner}" : "あなたと {owner} のグループ {group} で共有中", "Shared with you by {owner}" : "{owner} より共有中", "Choose a password for the mail share" : "メール共有のパスワードを選択", @@ -140,14 +142,12 @@ OC.L10N.register( "remote" : "リモート", "email" : "メール", "shared by {sharer}" : "共有した人 {sharer}", - "Unshare" : "共有解除", "Can reshare" : "再共有可能", "Can edit" : "編集可能", "Can create" : "作成可能", "Can change" : "変更可能", "Can delete" : "削除可能", "Access control" : "アクセス制御", - "Could not unshare" : "共有の解除ができませんでした", "Error while sharing" : "共有でエラーが発生しました", "Share details could not be loaded for this item." : "共有の詳細はこのアイテムによりロードできませんでした。", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["オートコンプリートには{count}文字以上必要です"], @@ -155,9 +155,6 @@ OC.L10N.register( "No users or groups found for {search}" : "{search} の検索でユーザー、グループが見つかりません", "No users found for {search}" : "{search} のユーザーはいませんでした", "An error occurred. Please try again" : "エラーが発生しました。もう一度実行してください。", - "{sharee} (group)" : "{sharee} (グループ)", - "{sharee} (remote)" : "{sharee} (リモート)", - "{sharee} (email)" : "{sharee} (メール)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "共有", "Name or email address..." : "名前またはメールアドレス", @@ -281,6 +278,9 @@ OC.L10N.register( "Error setting expiration date" : "有効期限の設定でエラー発生", "The public link will expire no later than {days} days after it is created" : "URLによる共有は、作成してから {days} 日以内に有効期限切れになります", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} がリンク経由で共有", + "{sharee} (group)" : "{sharee} (グループ)", + "{sharee} (remote)" : "{sharee} (リモート)", + "{sharee} (email)" : "{sharee} (メール)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "ユーザー名、グループ、クラウド統合ID、メールアドレスで共有", "Share with other people by entering a user or group or a federated cloud ID." : "ユーザー名、グループ、クラウド統合IDで共有", "Share with other people by entering a user or group or an email address." : "ユーザー名やグループ名、メールアドレスで共有", diff --git a/core/l10n/ja.json b/core/l10n/ja.json index 1a290bfc641..75e65c805c7 100644 --- a/core/l10n/ja.json +++ b/core/l10n/ja.json @@ -130,7 +130,9 @@ "Set expiration date" : "有効期限を設定", "Expiration" : "期限切れ", "Expiration date" : "有効期限", + "Unshare" : "共有解除", "Share link" : "URLで共有", + "Could not unshare" : "共有の解除ができませんでした", "Shared with you and the group {group} by {owner}" : "あなたと {owner} のグループ {group} で共有中", "Shared with you by {owner}" : "{owner} より共有中", "Choose a password for the mail share" : "メール共有のパスワードを選択", @@ -138,14 +140,12 @@ "remote" : "リモート", "email" : "メール", "shared by {sharer}" : "共有した人 {sharer}", - "Unshare" : "共有解除", "Can reshare" : "再共有可能", "Can edit" : "編集可能", "Can create" : "作成可能", "Can change" : "変更可能", "Can delete" : "削除可能", "Access control" : "アクセス制御", - "Could not unshare" : "共有の解除ができませんでした", "Error while sharing" : "共有でエラーが発生しました", "Share details could not be loaded for this item." : "共有の詳細はこのアイテムによりロードできませんでした。", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["オートコンプリートには{count}文字以上必要です"], @@ -153,9 +153,6 @@ "No users or groups found for {search}" : "{search} の検索でユーザー、グループが見つかりません", "No users found for {search}" : "{search} のユーザーはいませんでした", "An error occurred. Please try again" : "エラーが発生しました。もう一度実行してください。", - "{sharee} (group)" : "{sharee} (グループ)", - "{sharee} (remote)" : "{sharee} (リモート)", - "{sharee} (email)" : "{sharee} (メール)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "共有", "Name or email address..." : "名前またはメールアドレス", @@ -279,6 +276,9 @@ "Error setting expiration date" : "有効期限の設定でエラー発生", "The public link will expire no later than {days} days after it is created" : "URLによる共有は、作成してから {days} 日以内に有効期限切れになります", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} がリンク経由で共有", + "{sharee} (group)" : "{sharee} (グループ)", + "{sharee} (remote)" : "{sharee} (リモート)", + "{sharee} (email)" : "{sharee} (メール)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "ユーザー名、グループ、クラウド統合ID、メールアドレスで共有", "Share with other people by entering a user or group or a federated cloud ID." : "ユーザー名、グループ、クラウド統合IDで共有", "Share with other people by entering a user or group or an email address." : "ユーザー名やグループ名、メールアドレスで共有", diff --git a/core/l10n/ka_GE.js b/core/l10n/ka_GE.js index c1b5a9c3029..735bc40472a 100644 --- a/core/l10n/ka_GE.js +++ b/core/l10n/ka_GE.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "მიუთითეთ ვადის გასვლის დრო", "Expiration" : "ვადის გასვლა", "Expiration date" : "ვადის გასვლის დრო", + "Unshare" : "გაზიარების შეწყვეტა", "Share link" : "გააზიარეთ ბმული", + "Could not unshare" : "გაზიარების შეწყვეტა ვერ მოხერხდა", "Shared with you and the group {group} by {owner}" : "თქვენ და {group} ჯგუფს გაგიზიარდათ მომხმარებლისგან {owner}", "Shared with you by {owner}" : "თქვენთან გაზიარდა მომხმარებლისგან {owner}", "Choose a password for the mail share" : "აირჩიეთ პაროლი ელ-ფოსტით გაზიარებისთვის", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "დისტანციური", "email" : "ელ-ფოსტა", "shared by {sharer}" : "გააზიარა მომხმარებელმა {sharer}", - "Unshare" : "გაზიარების შეწყვეტა", "Can reshare" : "შეუძლია ხელახალი გაზიარება", "Can edit" : "შეუძლია შეცვლა", "Can create" : "შეუძლია შექმნა", "Can change" : "შეუძლია ცვლილება", "Can delete" : "შეუძლია გაუქმება", "Access control" : "დაშვების კონტროლი", - "Could not unshare" : "გაზიარების შეწყვეტა ვერ მოხერხდა", "Error while sharing" : "შეცდომა გაზიარების დროს", "Share details could not be loaded for this item." : "ამ ობიექტისთვის გაზიარების დეტალები ვერ ჩაიტვირთა.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["ავტო-დასრულებისთვის საჭიროა მინიმუმ {count} სიბმოლო","ავტო-დასრულებისთვის საჭიროა მინიმუმ {count} სიბმოლო"], @@ -169,9 +169,6 @@ OC.L10N.register( "No users or groups found for {search}" : "მომხმარებლები და ჯგუფები {search}-ისთვის არ იქნა ნაპოვნი", "No users found for {search}" : "მომხმარებლები {search}-ისთვის არ იქნა ნაპოვნი", "An error occurred. Please try again" : "წარმოიშვა შეცდომა. გთხოვთ სცადოთ ახლიდან.", - "{sharee} (group)" : "{sharee} (ჯგუფი)", - "{sharee} (remote)" : "{sharee} (დისტანციური)", - "{sharee} (email)" : "{sharee} (ელ-ფოსტა)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "გაზიარება", "Name or email address..." : "სახელი ან ელ-ფოსტის მისამართი...", @@ -315,6 +312,9 @@ OC.L10N.register( "Error setting expiration date" : "ვადის გასვლის მითითებისას წარმოიშვა შეცდომა", "The public link will expire no later than {days} days after it is created" : "საზოგადო ბმული გაუქმედება შექმნის მომენტიდან {days} დღის შემდეგ", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} მომხმარებელმა გააზიარა ბმულით", + "{sharee} (group)" : "{sharee} (ჯგუფი)", + "{sharee} (remote)" : "{sharee} (დისტანციური)", + "{sharee} (email)" : "{sharee} (ელ-ფოსტა)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "გაუზიარეთ სხვა ადამიანებს მოხმარებლის, ჯგუფის, ფედერალური ქლაუდ ID-ის ან ელ-ფოსტის მისამართის შეყვანით.", "Share with other people by entering a user or group or a federated cloud ID." : "გაუზიარეთ სხვა ადამიანებს, მომხმარებლის, ჯგუფის ან ფედერალური ქლაუდ ID-ის შეყვანით.", "Share with other people by entering a user or group or an email address." : "გაუზიარეთ სხვა ადამიანებს მომხმარებლის, ჯგუფის ან ელ-ფოსტის მისამართის შეყვანით.", diff --git a/core/l10n/ka_GE.json b/core/l10n/ka_GE.json index f85e63cf772..373315d106a 100644 --- a/core/l10n/ka_GE.json +++ b/core/l10n/ka_GE.json @@ -144,7 +144,9 @@ "Set expiration date" : "მიუთითეთ ვადის გასვლის დრო", "Expiration" : "ვადის გასვლა", "Expiration date" : "ვადის გასვლის დრო", + "Unshare" : "გაზიარების შეწყვეტა", "Share link" : "გააზიარეთ ბმული", + "Could not unshare" : "გაზიარების შეწყვეტა ვერ მოხერხდა", "Shared with you and the group {group} by {owner}" : "თქვენ და {group} ჯგუფს გაგიზიარდათ მომხმარებლისგან {owner}", "Shared with you by {owner}" : "თქვენთან გაზიარდა მომხმარებლისგან {owner}", "Choose a password for the mail share" : "აირჩიეთ პაროლი ელ-ფოსტით გაზიარებისთვის", @@ -152,14 +154,12 @@ "remote" : "დისტანციური", "email" : "ელ-ფოსტა", "shared by {sharer}" : "გააზიარა მომხმარებელმა {sharer}", - "Unshare" : "გაზიარების შეწყვეტა", "Can reshare" : "შეუძლია ხელახალი გაზიარება", "Can edit" : "შეუძლია შეცვლა", "Can create" : "შეუძლია შექმნა", "Can change" : "შეუძლია ცვლილება", "Can delete" : "შეუძლია გაუქმება", "Access control" : "დაშვების კონტროლი", - "Could not unshare" : "გაზიარების შეწყვეტა ვერ მოხერხდა", "Error while sharing" : "შეცდომა გაზიარების დროს", "Share details could not be loaded for this item." : "ამ ობიექტისთვის გაზიარების დეტალები ვერ ჩაიტვირთა.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["ავტო-დასრულებისთვის საჭიროა მინიმუმ {count} სიბმოლო","ავტო-დასრულებისთვის საჭიროა მინიმუმ {count} სიბმოლო"], @@ -167,9 +167,6 @@ "No users or groups found for {search}" : "მომხმარებლები და ჯგუფები {search}-ისთვის არ იქნა ნაპოვნი", "No users found for {search}" : "მომხმარებლები {search}-ისთვის არ იქნა ნაპოვნი", "An error occurred. Please try again" : "წარმოიშვა შეცდომა. გთხოვთ სცადოთ ახლიდან.", - "{sharee} (group)" : "{sharee} (ჯგუფი)", - "{sharee} (remote)" : "{sharee} (დისტანციური)", - "{sharee} (email)" : "{sharee} (ელ-ფოსტა)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "გაზიარება", "Name or email address..." : "სახელი ან ელ-ფოსტის მისამართი...", @@ -313,6 +310,9 @@ "Error setting expiration date" : "ვადის გასვლის მითითებისას წარმოიშვა შეცდომა", "The public link will expire no later than {days} days after it is created" : "საზოგადო ბმული გაუქმედება შექმნის მომენტიდან {days} დღის შემდეგ", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} მომხმარებელმა გააზიარა ბმულით", + "{sharee} (group)" : "{sharee} (ჯგუფი)", + "{sharee} (remote)" : "{sharee} (დისტანციური)", + "{sharee} (email)" : "{sharee} (ელ-ფოსტა)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "გაუზიარეთ სხვა ადამიანებს მოხმარებლის, ჯგუფის, ფედერალური ქლაუდ ID-ის ან ელ-ფოსტის მისამართის შეყვანით.", "Share with other people by entering a user or group or a federated cloud ID." : "გაუზიარეთ სხვა ადამიანებს, მომხმარებლის, ჯგუფის ან ფედერალური ქლაუდ ID-ის შეყვანით.", "Share with other people by entering a user or group or an email address." : "გაუზიარეთ სხვა ადამიანებს მომხმარებლის, ჯგუფის ან ელ-ფოსტის მისამართის შეყვანით.", diff --git a/core/l10n/ko.js b/core/l10n/ko.js index 3fb9985a83f..65c534aae28 100644 --- a/core/l10n/ko.js +++ b/core/l10n/ko.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "유지 보수 모드 켜짐", "Turned off maintenance mode" : "유지 보수 모드 꺼짐", "Maintenance mode is kept active" : "유지 보수 모드가 켜져 있음", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Cron이 끝날때까지 기다리는중(5초후에 다시 확인)...", "Updating database schema" : "데이터베이스 스키마 업데이트 중", "Updated database" : "데이터베이스 업데이트 됨", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "데이터베이스 스키마 업데이트 가능 여부 확인 중(데이터베이스 크기에 따라서 오래 걸릴 수도 있습니다)", @@ -162,7 +161,9 @@ OC.L10N.register( "Set expiration date" : "만료 날짜 설정", "Expiration" : "만료", "Expiration date" : "만료 날짜", + "Unshare" : "공유 해제", "Share link" : "링크 공유", + "Could not unshare" : "공유 해제할 수 없음", "Shared with you and the group {group} by {owner}" : "{owner} 님이 여러분 및 그룹 {group}와(과) 공유 중", "Shared with you by {owner}" : "{owner} 님이 공유 중", "Choose a password for the mail share" : "이메일 공유 암호 입력", @@ -170,14 +171,12 @@ OC.L10N.register( "remote" : "원격", "email" : "이메일", "shared by {sharer}" : "{sharer} 님이 공유함", - "Unshare" : "공유 해제", "Can reshare" : "재공유 가능", "Can edit" : "편집 가능", "Can create" : "생성 가능", "Can change" : "변경 가능", "Can delete" : "삭제 가능", "Access control" : "접근 제어", - "Could not unshare" : "공유 해제할 수 없음", "Error while sharing" : "공유하는 중 오류 발생", "Share details could not be loaded for this item." : "이 항목의 공유 정보를 불러올 수 없습니다.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["자동 완성을 시작하려면 최소 {count}글자를 입력해야 합니다"], @@ -185,9 +184,6 @@ OC.L10N.register( "No users or groups found for {search}" : "{search} 사용자나 그룹을 찾을 수 없음", "No users found for {search}" : "{search} 사용자를 찾을 수 없음", "An error occurred. Please try again" : "오류가 발생했습니다. 다시 시도하십시오.", - "{sharee} (group)" : "{sharee}(그룹)", - "{sharee} (remote)" : "{sharee}(원격)", - "{sharee} (email)" : "{sharee}(이메일)", "{sharee} ({type}, {owner})" : "{sharee}({type}, {owner})", "Share" : "공유", "Name or email address..." : "이름이나 이메일 주소...", @@ -331,6 +327,9 @@ OC.L10N.register( "Error setting expiration date" : "만료 날짜 설정 오류", "The public link will expire no later than {days} days after it is created" : "공개 링크를 만든 후 최대 {days}일까지 유지됩니다", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} 님이 링크를 통해 공유", + "{sharee} (group)" : "{sharee}(그룹)", + "{sharee} (remote)" : "{sharee}(원격)", + "{sharee} (email)" : "{sharee}(이메일)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "사용자나 그룹 이름, 연합 클라우드 ID 및 이메일 주소를 입력해서 다른 사람과 공유하십시오.", "Share with other people by entering a user or group or a federated cloud ID." : "사용자나 그룹 이름, 연합 클라우드 ID를 입력해서 다른 사람과 공유하십시오.", "Share with other people by entering a user or group or an email address." : "사용자나 그룹 이름 및 이메일 주소를 입력해서 다른 사람과 공유하십시오.", diff --git a/core/l10n/ko.json b/core/l10n/ko.json index 4168d836fff..a1794a00cd8 100644 --- a/core/l10n/ko.json +++ b/core/l10n/ko.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "유지 보수 모드 켜짐", "Turned off maintenance mode" : "유지 보수 모드 꺼짐", "Maintenance mode is kept active" : "유지 보수 모드가 켜져 있음", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Cron이 끝날때까지 기다리는중(5초후에 다시 확인)...", "Updating database schema" : "데이터베이스 스키마 업데이트 중", "Updated database" : "데이터베이스 업데이트 됨", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "데이터베이스 스키마 업데이트 가능 여부 확인 중(데이터베이스 크기에 따라서 오래 걸릴 수도 있습니다)", @@ -160,7 +159,9 @@ "Set expiration date" : "만료 날짜 설정", "Expiration" : "만료", "Expiration date" : "만료 날짜", + "Unshare" : "공유 해제", "Share link" : "링크 공유", + "Could not unshare" : "공유 해제할 수 없음", "Shared with you and the group {group} by {owner}" : "{owner} 님이 여러분 및 그룹 {group}와(과) 공유 중", "Shared with you by {owner}" : "{owner} 님이 공유 중", "Choose a password for the mail share" : "이메일 공유 암호 입력", @@ -168,14 +169,12 @@ "remote" : "원격", "email" : "이메일", "shared by {sharer}" : "{sharer} 님이 공유함", - "Unshare" : "공유 해제", "Can reshare" : "재공유 가능", "Can edit" : "편집 가능", "Can create" : "생성 가능", "Can change" : "변경 가능", "Can delete" : "삭제 가능", "Access control" : "접근 제어", - "Could not unshare" : "공유 해제할 수 없음", "Error while sharing" : "공유하는 중 오류 발생", "Share details could not be loaded for this item." : "이 항목의 공유 정보를 불러올 수 없습니다.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["자동 완성을 시작하려면 최소 {count}글자를 입력해야 합니다"], @@ -183,9 +182,6 @@ "No users or groups found for {search}" : "{search} 사용자나 그룹을 찾을 수 없음", "No users found for {search}" : "{search} 사용자를 찾을 수 없음", "An error occurred. Please try again" : "오류가 발생했습니다. 다시 시도하십시오.", - "{sharee} (group)" : "{sharee}(그룹)", - "{sharee} (remote)" : "{sharee}(원격)", - "{sharee} (email)" : "{sharee}(이메일)", "{sharee} ({type}, {owner})" : "{sharee}({type}, {owner})", "Share" : "공유", "Name or email address..." : "이름이나 이메일 주소...", @@ -329,6 +325,9 @@ "Error setting expiration date" : "만료 날짜 설정 오류", "The public link will expire no later than {days} days after it is created" : "공개 링크를 만든 후 최대 {days}일까지 유지됩니다", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} 님이 링크를 통해 공유", + "{sharee} (group)" : "{sharee}(그룹)", + "{sharee} (remote)" : "{sharee}(원격)", + "{sharee} (email)" : "{sharee}(이메일)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "사용자나 그룹 이름, 연합 클라우드 ID 및 이메일 주소를 입력해서 다른 사람과 공유하십시오.", "Share with other people by entering a user or group or a federated cloud ID." : "사용자나 그룹 이름, 연합 클라우드 ID를 입력해서 다른 사람과 공유하십시오.", "Share with other people by entering a user or group or an email address." : "사용자나 그룹 이름 및 이메일 주소를 입력해서 다른 사람과 공유하십시오.", diff --git a/core/l10n/lt_LT.js b/core/l10n/lt_LT.js index b189c271038..6f6f4e23f3d 100644 --- a/core/l10n/lt_LT.js +++ b/core/l10n/lt_LT.js @@ -133,7 +133,9 @@ OC.L10N.register( "Set expiration date" : "Nustatykite veikimo pabaigos datą", "Expiration" : "Veikimo pabaiga", "Expiration date" : "Veikimo pabaigos data", + "Unshare" : "Nebesidalinti", "Share link" : "Dalintis nuoroda", + "Could not unshare" : "Negalima nustoti dalintis", "Shared with you and the group {group} by {owner}" : "{owner} pasidalino su Jumis ir {group} grupe", "Shared with you by {owner}" : "{owner} pasidalino su Jumis ", "Choose a password for the mail share" : "Pasirinkite slaptažodį pasidalinimui per elektroninį paštą", @@ -141,14 +143,12 @@ OC.L10N.register( "remote" : "nuotolinis", "email" : "elektroninis paštas", "shared by {sharer}" : "pasidalino {sharer}", - "Unshare" : "Nebesidalinti", "Can reshare" : "Galima dalintis su kitais", "Can edit" : "Galima redaguoti", "Can create" : "Galima kurti nauja", "Can change" : "Galima keisti", "Can delete" : "Galima trinti", "Access control" : "Prieigos valdymas", - "Could not unshare" : "Negalima nustoti dalintis", "Error while sharing" : "Klaida, dalijimosi metu", "Share details could not be loaded for this item." : "Dalinimosi detalės negali būti atskleistos šiai bylai", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius","Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius","Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius","Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius"], @@ -156,9 +156,6 @@ OC.L10N.register( "No users or groups found for {search}" : "Nerasta vartotojų ar grupių pagal paieškos kriterijų: {search}", "No users found for {search}" : "Nerasta vartotojų pagal paieškos kriterijų: {search}", "An error occurred. Please try again" : "Įvyko klaida. Bandykite dar kartą", - "{sharee} (group)" : "{sharee} (grupė)", - "{sharee} (remote)" : "{sharee} (nuotolinis)", - "{sharee} (email)" : "{sharee} (elektroninis paštas)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Dalintis", "Name or email address..." : "Vardas arba elektroninio pašto adresas...", @@ -283,6 +280,9 @@ OC.L10N.register( "Error setting expiration date" : "Klaida nustatant dalinimosi pabaigos laiką", "The public link will expire no later than {days} days after it is created" : "Nuoroda veiks ne mažiau kaip {days} dienas nuo sukūrimo", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} pasidalino per nuorodą", + "{sharee} (group)" : "{sharee} (grupė)", + "{sharee} (remote)" : "{sharee} (nuotolinis)", + "{sharee} (email)" : "{sharee} (elektroninis paštas)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Pasidalinti su kitais asmenimis galima įvedus vartotojo ar grupės vardą, NextCloud tinklo kompiuterio ID arba elektroninio pašto adresą.", "Share with other people by entering a user or group or a federated cloud ID." : "Pasidalinti su kitais asmenimis galima įvedus vartotojo ar grupės vardą arba NextCloud tinklo kompiuterio ID.", "Share with other people by entering a user or group or an email address." : "Pasidalinti su kitais asmenimis galima įvedus vartotojo ar grupės vardą arba elektroninio pašto adresą.", diff --git a/core/l10n/lt_LT.json b/core/l10n/lt_LT.json index 6206e0193c3..f13a21ff580 100644 --- a/core/l10n/lt_LT.json +++ b/core/l10n/lt_LT.json @@ -131,7 +131,9 @@ "Set expiration date" : "Nustatykite veikimo pabaigos datą", "Expiration" : "Veikimo pabaiga", "Expiration date" : "Veikimo pabaigos data", + "Unshare" : "Nebesidalinti", "Share link" : "Dalintis nuoroda", + "Could not unshare" : "Negalima nustoti dalintis", "Shared with you and the group {group} by {owner}" : "{owner} pasidalino su Jumis ir {group} grupe", "Shared with you by {owner}" : "{owner} pasidalino su Jumis ", "Choose a password for the mail share" : "Pasirinkite slaptažodį pasidalinimui per elektroninį paštą", @@ -139,14 +141,12 @@ "remote" : "nuotolinis", "email" : "elektroninis paštas", "shared by {sharer}" : "pasidalino {sharer}", - "Unshare" : "Nebesidalinti", "Can reshare" : "Galima dalintis su kitais", "Can edit" : "Galima redaguoti", "Can create" : "Galima kurti nauja", "Can change" : "Galima keisti", "Can delete" : "Galima trinti", "Access control" : "Prieigos valdymas", - "Could not unshare" : "Negalima nustoti dalintis", "Error while sharing" : "Klaida, dalijimosi metu", "Share details could not be loaded for this item." : "Dalinimosi detalės negali būti atskleistos šiai bylai", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius","Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius","Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius","Norint pasinaudoti automatinio užpildymo paslauga, reikia suvesti bent {count} simbolius"], @@ -154,9 +154,6 @@ "No users or groups found for {search}" : "Nerasta vartotojų ar grupių pagal paieškos kriterijų: {search}", "No users found for {search}" : "Nerasta vartotojų pagal paieškos kriterijų: {search}", "An error occurred. Please try again" : "Įvyko klaida. Bandykite dar kartą", - "{sharee} (group)" : "{sharee} (grupė)", - "{sharee} (remote)" : "{sharee} (nuotolinis)", - "{sharee} (email)" : "{sharee} (elektroninis paštas)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Dalintis", "Name or email address..." : "Vardas arba elektroninio pašto adresas...", @@ -281,6 +278,9 @@ "Error setting expiration date" : "Klaida nustatant dalinimosi pabaigos laiką", "The public link will expire no later than {days} days after it is created" : "Nuoroda veiks ne mažiau kaip {days} dienas nuo sukūrimo", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} pasidalino per nuorodą", + "{sharee} (group)" : "{sharee} (grupė)", + "{sharee} (remote)" : "{sharee} (nuotolinis)", + "{sharee} (email)" : "{sharee} (elektroninis paštas)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Pasidalinti su kitais asmenimis galima įvedus vartotojo ar grupės vardą, NextCloud tinklo kompiuterio ID arba elektroninio pašto adresą.", "Share with other people by entering a user or group or a federated cloud ID." : "Pasidalinti su kitais asmenimis galima įvedus vartotojo ar grupės vardą arba NextCloud tinklo kompiuterio ID.", "Share with other people by entering a user or group or an email address." : "Pasidalinti su kitais asmenimis galima įvedus vartotojo ar grupės vardą arba elektroninio pašto adresą.", diff --git a/core/l10n/lv.js b/core/l10n/lv.js index 48e1297cc01..de0c8198aaf 100644 --- a/core/l10n/lv.js +++ b/core/l10n/lv.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Ieslēgts uzturēšanas režīms", "Turned off maintenance mode" : "Izslēgts uzturēšanas režīms", "Maintenance mode is kept active" : "Uzturēšanas režīms ir paturēts aktīvs", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Gaidām līdz cron pabeigs darbu (atkārtoti pārbaudām ik pēc 5 sekundēm) ...", "Updating database schema" : "Atjaunina datu bāzes shēmu", "Updated database" : "Atjaunināta datu bāze", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Pārbauda vai datu bāzes shēma var būt atjaunināma (tas var prasīt laiku atkarībā no datu bāzes izmēriem)", @@ -146,8 +145,10 @@ OC.L10N.register( "Set expiration date" : "Iestatiet termiņa datumu", "Expiration" : "Termiņš", "Expiration date" : "Termiņa datums", + "Unshare" : "Pārtraukt koplietošanu", "Share link" : "Koplietot saiti", - "Enable" : "Iespējot", + "Password protect by Talk" : "Aizsargāts ar paroli no Talk", + "Could not unshare" : "Nevarēja pārtraukt koplietošanu", "Shared with you and the group {group} by {owner}" : "{owner} koplietoja ar jums un grupu {group}", "Shared with you and {circle} by {owner}" : " {owner} koplietoja ar tevi un {circle}", "Shared with you and the conversation {conversation} by {owner}" : "Dalīts ar tevi un sarunu {conversation} no {owner}", @@ -157,23 +158,17 @@ OC.L10N.register( "email" : "e-pasts", "conversation" : "saruna", "shared by {sharer}" : "Koplietoja {sharer}", - "Unshare" : "Pārtraukt koplietošanu", "Can reshare" : "Var atkārtoti kopīgot", "Can edit" : "Var rediģēt", "Can create" : "Var izveidot", "Can change" : "Var mainīt", "Can delete" : "Var dzēst", - "Password protect by Talk" : "Aizsargāts ar paroli no Talk", "Access control" : "Piekļuves vadība", - "Could not unshare" : "Nevarēja pārtraukt koplietošanu", "Error while sharing" : "Kļūda, daloties", "Share details could not be loaded for this item." : "Šim nevarēja ielādēt koplietošanas detaļas.", "No users or groups found for {search}" : "Pēc {search} netika atrasts neviens lietotājs vai grupa", "No users found for {search}" : "Pēc {search} netika atrasts neviens lietotājs", "An error occurred. Please try again" : "Notika kļūda. Mēģini vēlreiz.", - "{sharee} (group)" : "{sharee} (grupa)", - "{sharee} (remote)" : "{sharee} (attālināti)", - "{sharee} (email)" : "{sharee} (e-pasts)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Koplietot", "Name or email address..." : "Vārds vai e-pasta adrese...", @@ -297,6 +292,9 @@ OC.L10N.register( "Error setting expiration date" : "Kļūda, iestatot termiņa datumu", "The public link will expire no later than {days} days after it is created" : "Šis links beigs strādāt pēc ne vēlāk kā {days} dienām pēc tam kad tas tiks izveidots", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} koplietots ar saiti", + "{sharee} (group)" : "{sharee} (grupa)", + "{sharee} (remote)" : "{sharee} (attālināti)", + "{sharee} (email)" : "{sharee} (e-pasts)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Dalīties ar citiem cilvēkiem ievadot lietotāju, grupu, federated cloud ID vai e-pasta adresi.", "Share with other people by entering a user or group or a federated cloud ID." : "Dalīties ar citiem cilvēkiem ievadot lietotāju, grupu vai federated cloud ID.", "Share with other people by entering a user or group or an email address." : "Dalīties ar citiem cilvēkiem ievadot lietotāju, grupu vai e-pasta adresi.", @@ -315,6 +313,7 @@ OC.L10N.register( "%s will be updated to version %s" : "%s tiks atjaunināts uz versiju %s", "This page will refresh itself when the %s instance is available again." : "Lapa tiks atsvaidzināta kad %s instance atkal ir pieejama.", "Thank you for your patience." : "Paldies par jūsu pacietību.", - "Back to log in" : "Atpakaļ uz pierakstīšanos" + "Back to log in" : "Atpakaļ uz pierakstīšanos", + "Enable" : "Iespējot" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); diff --git a/core/l10n/lv.json b/core/l10n/lv.json index 7745e88c50a..7d0f6f4f4ec 100644 --- a/core/l10n/lv.json +++ b/core/l10n/lv.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Ieslēgts uzturēšanas režīms", "Turned off maintenance mode" : "Izslēgts uzturēšanas režīms", "Maintenance mode is kept active" : "Uzturēšanas režīms ir paturēts aktīvs", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Gaidām līdz cron pabeigs darbu (atkārtoti pārbaudām ik pēc 5 sekundēm) ...", "Updating database schema" : "Atjaunina datu bāzes shēmu", "Updated database" : "Atjaunināta datu bāze", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Pārbauda vai datu bāzes shēma var būt atjaunināma (tas var prasīt laiku atkarībā no datu bāzes izmēriem)", @@ -144,8 +143,10 @@ "Set expiration date" : "Iestatiet termiņa datumu", "Expiration" : "Termiņš", "Expiration date" : "Termiņa datums", + "Unshare" : "Pārtraukt koplietošanu", "Share link" : "Koplietot saiti", - "Enable" : "Iespējot", + "Password protect by Talk" : "Aizsargāts ar paroli no Talk", + "Could not unshare" : "Nevarēja pārtraukt koplietošanu", "Shared with you and the group {group} by {owner}" : "{owner} koplietoja ar jums un grupu {group}", "Shared with you and {circle} by {owner}" : " {owner} koplietoja ar tevi un {circle}", "Shared with you and the conversation {conversation} by {owner}" : "Dalīts ar tevi un sarunu {conversation} no {owner}", @@ -155,23 +156,17 @@ "email" : "e-pasts", "conversation" : "saruna", "shared by {sharer}" : "Koplietoja {sharer}", - "Unshare" : "Pārtraukt koplietošanu", "Can reshare" : "Var atkārtoti kopīgot", "Can edit" : "Var rediģēt", "Can create" : "Var izveidot", "Can change" : "Var mainīt", "Can delete" : "Var dzēst", - "Password protect by Talk" : "Aizsargāts ar paroli no Talk", "Access control" : "Piekļuves vadība", - "Could not unshare" : "Nevarēja pārtraukt koplietošanu", "Error while sharing" : "Kļūda, daloties", "Share details could not be loaded for this item." : "Šim nevarēja ielādēt koplietošanas detaļas.", "No users or groups found for {search}" : "Pēc {search} netika atrasts neviens lietotājs vai grupa", "No users found for {search}" : "Pēc {search} netika atrasts neviens lietotājs", "An error occurred. Please try again" : "Notika kļūda. Mēģini vēlreiz.", - "{sharee} (group)" : "{sharee} (grupa)", - "{sharee} (remote)" : "{sharee} (attālināti)", - "{sharee} (email)" : "{sharee} (e-pasts)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Koplietot", "Name or email address..." : "Vārds vai e-pasta adrese...", @@ -295,6 +290,9 @@ "Error setting expiration date" : "Kļūda, iestatot termiņa datumu", "The public link will expire no later than {days} days after it is created" : "Šis links beigs strādāt pēc ne vēlāk kā {days} dienām pēc tam kad tas tiks izveidots", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} koplietots ar saiti", + "{sharee} (group)" : "{sharee} (grupa)", + "{sharee} (remote)" : "{sharee} (attālināti)", + "{sharee} (email)" : "{sharee} (e-pasts)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Dalīties ar citiem cilvēkiem ievadot lietotāju, grupu, federated cloud ID vai e-pasta adresi.", "Share with other people by entering a user or group or a federated cloud ID." : "Dalīties ar citiem cilvēkiem ievadot lietotāju, grupu vai federated cloud ID.", "Share with other people by entering a user or group or an email address." : "Dalīties ar citiem cilvēkiem ievadot lietotāju, grupu vai e-pasta adresi.", @@ -313,6 +311,7 @@ "%s will be updated to version %s" : "%s tiks atjaunināts uz versiju %s", "This page will refresh itself when the %s instance is available again." : "Lapa tiks atsvaidzināta kad %s instance atkal ir pieejama.", "Thank you for your patience." : "Paldies par jūsu pacietību.", - "Back to log in" : "Atpakaļ uz pierakstīšanos" + "Back to log in" : "Atpakaļ uz pierakstīšanos", + "Enable" : "Iespējot" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" }
\ No newline at end of file diff --git a/core/l10n/nb.js b/core/l10n/nb.js index ee1bbf7e246..ac5a7069436 100644 --- a/core/l10n/nb.js +++ b/core/l10n/nb.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Vedlikeholdsmodus aktivt", "Turned off maintenance mode" : "Vedlikeholdsmodus ikke aktivt", "Maintenance mode is kept active" : "Vedlikeholdsmodus blir beholdt aktivt", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Venter på at cron skal bli ferdig (sjekk om 5 sekund)...", "Updating database schema" : "Oppdaterer database-skjemaet", "Updated database" : "Oppdaterte databasen", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Sjekker om databaseskjemaet kan oppdateres (dette kan ta lang tid hvis databasen er stor)", @@ -46,6 +45,7 @@ OC.L10N.register( "Checked for update of app \"%s\" in appstore" : "Så etter oppdateringer for programmet \"%s\" i program-butikk", "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Sjekker om databaseskjemaet for %s kan oppdateres (dette kan ta lang tid hvis databasen er stor)", "Checked database schema update for apps" : "Sjekket databaseskjema-oppdatering for programmer", + "Updated \"%1$s\" to %2$s" : "Oppdaterte \"%1$s\" til %2$s", "Set log level to debug" : "Sett loggnivå for feilsøking", "Reset log level" : "Standard loggnivå", "Starting code integrity check" : "Starter sjekk av kode-integritet", @@ -127,6 +127,7 @@ OC.L10N.register( "Check the background job settings" : "Kontroller instillinger for bakgrunnsjobb", "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." : "Denne tjeneren har ingen fungerende internett-forbindelse. Dette betyr at noen funksjoner, som tilknytning av eksterne lagre, varslinger om oppdateringer eller installering av tredjepartsprogrammer ikke vil virke. Fjerntilgang til filer og utsending av varsler på e-post vil kanskje ikke virke heller. Det anbefales å aktivere en internett-forbindelse for denne tjeneren hvis du vil ha full funksjonalitet.", "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>." : "Hurtigminne er ikke satt opp. For bedre ytelse bør du sette opp hurtigminne hvis det er tilgjengelig. Mer informasjon finnes i <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">dokumentasjonen</a>.", + "No suitable source for randomness found 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>." : "Ingen egnet kilde til tilfeldighet funnet av PHP som er svært motløst av sikkerhetshensyn. Mer informasjon finnes i <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">dokumentasjon</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." : "Du bruker PHP-{version}. Oppgrader PHP-versjonen for å utnytte <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{phpLink}\">ytelsen og sikkerhetsoppdateringene som tilbys av PHP Group</a, så fort din distribusjon støtter det.", "You are currently running PHP 5.6. The current major version of Nextcloud is the last that is supported on PHP 5.6. It is recommended to upgrade the PHP version to 7.0+ to be able to upgrade to Nextcloud 14." : "Du kjører nå PHP 5.6. Den nåværende hovedversjonen er den siste som støtter PHP 5.6. Det anbefales å oppgradere PHP-versjonen til 7.0+, for å kunne oppgradere til Nextcloud 14.", "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "Det omvendte mellomtjener-hodet er ikke satt opp rett, eller du kobler til Nextcloud fra en betrodd mellomtjener. Hvis ikke, er dette et sikkerhetsproblem, og kan tillate en angriper å forfalske deres IP-adresse slik den er synlig for Nextcloud. Ytterligere informasjon er å finne i <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">dokumentasjonen</a>.", @@ -148,6 +149,8 @@ OC.L10N.register( "Your data directory and files are probably accessible from the Internet. The .htaccess file is not working. It is strongly recommended that you configure your web server so that the data directory is no longer accessible, or move the data directory outside the web server document root." : "Datamappen og filene dine er sannsynligvis tilgjengelige fra Internett. .htaccess-filen fungerer ikke. Det anbefales sterkt at du setter opp vev-tjeneren slik at datamappen ikke kan nås eller at du flytter datamappen ut av vev-tjenerens dokumentrot.", "The \"{header}\" HTTP header is not set to \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "HTTP-hodet \"{header}\" er ikke satt opp likt \"{expected}\". Dette kan være en sikkerhet- eller personvernsrisiko og det anbefales at denne innstillingen endres.", "The \"{header}\" HTTP header is not set to \"{expected}\". Some features might not work correctly, as it is recommended to adjust this setting accordingly." : "HTTP-hodet \"{header}\" er ikke satt opp til å være likt \"{expected}\". Det kan hende noen funksjoner ikke fungerer rett, og det anbefales å justere denne innstillingen henholdsvis.", + "The \"{header}\" HTTP header doesn't contain \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "\"{header}\" HTTP hode mangler \"{expected}\". Dette er en sikkerhetsrisiko eller personverntrussel. Det er anbefalt å korrigere oppsett.", + "The \"{header}\" HTTP header is not set to \"{val1}\", \"{val2}\", \"{val3}\", \"{val4}\" or \"{val5}\". This can leak referer information. See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C Recommendation ↗</a>." : "\"{header}\" HTTP hode er satt til \"{val1}\", \"{val2}\", \"{val3}\", \"{val4}\" eller \"{val5}\". Dette kan gi lekasje i henvisningsinformasjon. Se <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C anbefalinger ↗</a>.", "The \"Strict-Transport-Security\" HTTP header is not set to at least \"{seconds}\" seconds. For enhanced security, it is recommended to enable HSTS as described in the <a href=\"{docUrl}\" rel=\"noreferrer noopener\">security tips ↗</a>." : "HTTP-overskriften \"Strict-Transport-Security\" er ikke satt til minst \"{sekunder}\" sekunder. For forbedret sikkerhet anbefales det å aktivere HSTS som beskrevet i <a href=\"{docUrl}\" rel=\"noreferrer noopener\">tips for bedre sikkerhet ↗</a>.", "Accessing site insecurely via HTTP. You are strongly adviced to set up your server to require HTTPS instead, as described in the <a href=\"{docUrl}\">security tips ↗</a>." : "Få tilgang til nettstedet usikkert via HTTP. Du er sterkt anbefalt å sette opp serveren din for å kreve HTTPS i stedet, som beskrevet i<a href=\"{docUrl}\">tips for bedre sikkerhet ↗</a>.", "Shared" : "Delt", @@ -156,6 +159,7 @@ OC.L10N.register( "Choose a password for the public link" : "Velg et passord for den offentlige lenken", "Choose a password for the public link or press the \"Enter\" key" : "Velg et passord for den offentlige lenken eller trykk \"Enter\"-tasten", "Copied!" : "Kopiert!", + "Copy link" : "Kopier lenke", "Not supported!" : "Ikke støttet!", "Press ⌘-C to copy." : "Trykk ⌘-C for å kopiere", "Press Ctrl-C to copy." : "Trykk Ctrl-C for å kopiere", @@ -173,11 +177,14 @@ OC.L10N.register( "Expiration" : "Utløpsdato", "Expiration date" : "Utløpsdato", "Note to recipient" : "Note til mottaker", + "Unshare" : "Avslutt deling", "Share link" : "Del lenke", - "Enable" : "Aktiver", + "Password protect by Talk" : "Passord beskyttet av Talk", + "Could not unshare" : "Kunne ikke avslutte deling", "Shared with you and the group {group} by {owner}" : "Delt med deg og gruppen {group} av {owner}", "Shared with you and {circle} by {owner}" : "Delt med deg og {circle} av {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Delt med deg og samtalen {conversation} av {owner}", + "Shared with you in a conversation by {owner}" : "Delt md deg i samtale med {owner}", "Shared with you by {owner}" : "Delt med deg av {owner}", "Choose a password for the mail share" : "Velg et passord for e-postlageret", "group" : "gruppe", @@ -186,15 +193,13 @@ OC.L10N.register( "email" : "e-post", "conversation" : "samtale", "shared by {sharer}" : "delt av {sharer}", - "Unshare" : "Avslutt deling", "Can reshare" : "Kan dele videre", "Can edit" : "Kan redigere", "Can create" : "Kan opprette", "Can change" : "Kan endre", "Can delete" : "Kan slette", - "Password protect by Talk" : "Passord beskyttet av Talk", "Access control" : "Tilgangskontroll", - "Could not unshare" : "Kunne ikke avslutte deling", + "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} delt via lenke", "Error while sharing" : "Feil under deling", "Share details could not be loaded for this item." : "Klarte ikke å laste inn detaljer om deling for dette elementet.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Minst {count} tegn er nødvendig for autofullføring","Minst {count} antall tegn er nødvendig for autofullføring"], @@ -203,12 +208,8 @@ OC.L10N.register( "No users found for {search}" : "Ingen brukere funnet for {search}", "An error occurred (\"{message}\"). Please try again" : "En feil inntraff (\"{message}\"). Prøv igjen", "An error occurred. Please try again" : "Det oppstod en feil. Prøv igjen", - "{sharee} (group)" : "{sharee} (gruppe)", - "{sharee} (remote)" : "{sharee} (ekstern)", "{sharee} (remote group)" : "{sharee} (remote group)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", "Share" : "Del", "Name or email address..." : "Navn eller e-postadresse…", "Name or federated cloud ID..." : "Navn eller sammenknyttet sky-ID…", @@ -250,6 +251,8 @@ OC.L10N.register( "Help" : "Hjelp", "Access forbidden" : "Tilgang nektet", "File not found" : "Finner ikke filen", + "The document could not be found on the server. Maybe the share was deleted or has expired?" : "Dokumentasjon kan ikke finnes på server. Er deling slettet eller utløpt?", + "Back to %s" : "Tilbake til %s", "Internal Server Error" : "Intern tjenerfeil.", "The server was unable to complete your request." : "Tjeneren kunne ikke fullføre din forespørsel.", "If this happens again, please send the technical details below to the server administrator." : "Hvis dette skjer igjen, send de tekniske detaljene nedenfor til tjeneradministratoren.", @@ -311,23 +314,30 @@ OC.L10N.register( "Forgot password?" : "Glemt passord?", "Back to login" : "Tilbake til innlogging", "Connect to your account" : "Koble til kontoen din", + "Please log in before granting %1$s access to your %2$s account." : "Logg inn før du tildeler %1$stilgang til din %2$skonto.", "App token" : "Program-symbol", "Grant access" : "Gi tilgang", "Alternative log in using app token" : "Alternativ logg inn ved hjelp av program kode", "Account access" : "Kontotilgang", + "You are about to grant %1$s access to your %2$s account." : "Du er i ferd med å tildele %1$s tilgang til din %2$skonto.", "Redirecting …" : "Videresender…", "New password" : "Nytt passord", "New Password" : "Nytt passord", "This share is password-protected" : "Denne deling er beskyttet med passord", "The password is wrong. Try again." : "Feil passord, forsøk igjen", "Two-factor authentication" : "Tofaktor autentisering", + "Enhanced security is enabled for your account. Choose a second factor for authentication:" : "Utvidet sikkerhet er tilgjengelig fo rdin konto. Velg en to-faktor for autentisering.", "Could not load at least one of your enabled two-factor auth methods. Please contact your admin." : "Kunne ikke laste minst en av de aktiverte tofaktor metodene. Ta kontakt med administrasjonen din.", + "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "To-faktor autentisering er aktivert men er ikke satt opp for din konto. Kontakt administrator for hjelp.", + "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "To-faktor autentisering er aktivert men er ikke satt opp for din konto. Bruk en av dine sikkerhet koder for å logge inn eller kontakt administrator for hjelp.", "Use backup code" : "Bruker sikkerhetskopi kode", "Cancel log in" : "Avbryt innlogging", "Error while validating your second factor" : "Feil under validering av din andre faktor", "Access through untrusted domain" : "Nå gjennom ubetrodd domene", "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." : "Kontakt din administrator. Hvis du er en administrator, sett opp innstillingen \"trusted_domains\" i config/config.php som eksemplet i config/config.sample.php.", + "Further information how to configure this can be found in the %1$sdocumentation%2$s." : "Ytterligere informasojn om oppsett finnes i %1$sdokumentasjon%2$s.", "App update required" : "Program-oppdatering kreves", + "%1$s will be updated to version %2$s" : "%1$soppdateres til versjon %2$s", "These apps will be updated:" : "Disse programmene vil bli oppdatert:", "These incompatible apps will be disabled:" : "Disse ikke-kompatible programmene vil bli deaktivert:", "The theme %s has been disabled." : "Drakten %s har blitt deaktivert.", @@ -340,7 +350,9 @@ OC.L10N.register( "For help, see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation</a>." : "For hjelp, les <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">dokumentasjonen</a>.", "I know that if I continue doing the update via web UI has the risk, that the request runs into a timeout and could cause data loss, but I have a backup and know how to restore my instance in case of a failure." : "Jeg vet at hvis jeg fortsetter oppdateringen via vev-grensesnittet er det en mulighet for datatap som følge av tidsavbrudd, men jeg har en sikkerhetskopi og vet hvordan jeg skal gjenopprette min installasjon hvis den feiler.", "Upgrade via web on my own risk" : "Oppgrader via vev på min egen risikio", + "Maintenance mode" : "Modus for vedlikehold", "This %s instance is currently in maintenance mode, which may take a while." : "Denne %s-instansen er for øyeblikket i vedlikeholdsmodus, noe som kan vare en stund.", + "This page will refresh itself when the instance is available again." : "Siden vil oppdatere seg selv når instans er tilgjengelig igjen.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakt systemadministratoren hvis denne meldingen var uventet eller ikke forsvinner.", "Updated \"%s\" to %s" : "Oppdaterte \"%s\" til %s", "%s (3rdparty)" : "%s (tredjepart)", @@ -364,6 +376,9 @@ OC.L10N.register( "Error setting expiration date" : "Kan ikke sette utløpsdato", "The public link will expire no later than {days} days after it is created" : "Den offentlige lenken vil utløpe senest {days} dager etter at den lages", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delt via lenke", + "{sharee} (group)" : "{sharee} (gruppe)", + "{sharee} (remote)" : "{sharee} (ekstern)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Del med andre ved å skrive inn en bruker, en gruppe, en sammenknyttet sky-ID eller en e-postadresse.", "Share with other people by entering a user or group or a federated cloud ID." : "Del med andre ved å skrive inn en bruker, en gruppe eller en sammenknyttet sky-ID", "Share with other people by entering a user or group or an email address." : "Del med andre ved å skrive inn en bruker, en gruppe, eller en e-postadresse.", @@ -394,6 +409,9 @@ OC.L10N.register( "Back to log in" : "Tilbake til innlogging", "You are about to grant %s access to your %s account." : "Du er i ferd med å gi %s tilgang til din %s konto.", "Depending on your configuration, this button could also work to trust the domain:" : "Avhengig av ditt oppsett, kan denne knappen også betro domenet.", + "Copy URL" : "Kopier URL", + "Enable" : "Aktiver", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Logg inn før du innvilger %s tilgang til din %s konto.", "Further information how to configure this can be found in the %sdocumentation%s." : "Ytterligere informasjon om hvordan du konfigurerer dette kan du finne i %sdokumentasjon%s." }, diff --git a/core/l10n/nb.json b/core/l10n/nb.json index af40462431d..f23ed4122a7 100644 --- a/core/l10n/nb.json +++ b/core/l10n/nb.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Vedlikeholdsmodus aktivt", "Turned off maintenance mode" : "Vedlikeholdsmodus ikke aktivt", "Maintenance mode is kept active" : "Vedlikeholdsmodus blir beholdt aktivt", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Venter på at cron skal bli ferdig (sjekk om 5 sekund)...", "Updating database schema" : "Oppdaterer database-skjemaet", "Updated database" : "Oppdaterte databasen", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Sjekker om databaseskjemaet kan oppdateres (dette kan ta lang tid hvis databasen er stor)", @@ -44,6 +43,7 @@ "Checked for update of app \"%s\" in appstore" : "Så etter oppdateringer for programmet \"%s\" i program-butikk", "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Sjekker om databaseskjemaet for %s kan oppdateres (dette kan ta lang tid hvis databasen er stor)", "Checked database schema update for apps" : "Sjekket databaseskjema-oppdatering for programmer", + "Updated \"%1$s\" to %2$s" : "Oppdaterte \"%1$s\" til %2$s", "Set log level to debug" : "Sett loggnivå for feilsøking", "Reset log level" : "Standard loggnivå", "Starting code integrity check" : "Starter sjekk av kode-integritet", @@ -125,6 +125,7 @@ "Check the background job settings" : "Kontroller instillinger for bakgrunnsjobb", "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." : "Denne tjeneren har ingen fungerende internett-forbindelse. Dette betyr at noen funksjoner, som tilknytning av eksterne lagre, varslinger om oppdateringer eller installering av tredjepartsprogrammer ikke vil virke. Fjerntilgang til filer og utsending av varsler på e-post vil kanskje ikke virke heller. Det anbefales å aktivere en internett-forbindelse for denne tjeneren hvis du vil ha full funksjonalitet.", "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>." : "Hurtigminne er ikke satt opp. For bedre ytelse bør du sette opp hurtigminne hvis det er tilgjengelig. Mer informasjon finnes i <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">dokumentasjonen</a>.", + "No suitable source for randomness found 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>." : "Ingen egnet kilde til tilfeldighet funnet av PHP som er svært motløst av sikkerhetshensyn. Mer informasjon finnes i <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">dokumentasjon</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." : "Du bruker PHP-{version}. Oppgrader PHP-versjonen for å utnytte <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{phpLink}\">ytelsen og sikkerhetsoppdateringene som tilbys av PHP Group</a, så fort din distribusjon støtter det.", "You are currently running PHP 5.6. The current major version of Nextcloud is the last that is supported on PHP 5.6. It is recommended to upgrade the PHP version to 7.0+ to be able to upgrade to Nextcloud 14." : "Du kjører nå PHP 5.6. Den nåværende hovedversjonen er den siste som støtter PHP 5.6. Det anbefales å oppgradere PHP-versjonen til 7.0+, for å kunne oppgradere til Nextcloud 14.", "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "Det omvendte mellomtjener-hodet er ikke satt opp rett, eller du kobler til Nextcloud fra en betrodd mellomtjener. Hvis ikke, er dette et sikkerhetsproblem, og kan tillate en angriper å forfalske deres IP-adresse slik den er synlig for Nextcloud. Ytterligere informasjon er å finne i <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">dokumentasjonen</a>.", @@ -146,6 +147,8 @@ "Your data directory and files are probably accessible from the Internet. The .htaccess file is not working. It is strongly recommended that you configure your web server so that the data directory is no longer accessible, or move the data directory outside the web server document root." : "Datamappen og filene dine er sannsynligvis tilgjengelige fra Internett. .htaccess-filen fungerer ikke. Det anbefales sterkt at du setter opp vev-tjeneren slik at datamappen ikke kan nås eller at du flytter datamappen ut av vev-tjenerens dokumentrot.", "The \"{header}\" HTTP header is not set to \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "HTTP-hodet \"{header}\" er ikke satt opp likt \"{expected}\". Dette kan være en sikkerhet- eller personvernsrisiko og det anbefales at denne innstillingen endres.", "The \"{header}\" HTTP header is not set to \"{expected}\". Some features might not work correctly, as it is recommended to adjust this setting accordingly." : "HTTP-hodet \"{header}\" er ikke satt opp til å være likt \"{expected}\". Det kan hende noen funksjoner ikke fungerer rett, og det anbefales å justere denne innstillingen henholdsvis.", + "The \"{header}\" HTTP header doesn't contain \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "\"{header}\" HTTP hode mangler \"{expected}\". Dette er en sikkerhetsrisiko eller personverntrussel. Det er anbefalt å korrigere oppsett.", + "The \"{header}\" HTTP header is not set to \"{val1}\", \"{val2}\", \"{val3}\", \"{val4}\" or \"{val5}\". This can leak referer information. See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C Recommendation ↗</a>." : "\"{header}\" HTTP hode er satt til \"{val1}\", \"{val2}\", \"{val3}\", \"{val4}\" eller \"{val5}\". Dette kan gi lekasje i henvisningsinformasjon. Se <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C anbefalinger ↗</a>.", "The \"Strict-Transport-Security\" HTTP header is not set to at least \"{seconds}\" seconds. For enhanced security, it is recommended to enable HSTS as described in the <a href=\"{docUrl}\" rel=\"noreferrer noopener\">security tips ↗</a>." : "HTTP-overskriften \"Strict-Transport-Security\" er ikke satt til minst \"{sekunder}\" sekunder. For forbedret sikkerhet anbefales det å aktivere HSTS som beskrevet i <a href=\"{docUrl}\" rel=\"noreferrer noopener\">tips for bedre sikkerhet ↗</a>.", "Accessing site insecurely via HTTP. You are strongly adviced to set up your server to require HTTPS instead, as described in the <a href=\"{docUrl}\">security tips ↗</a>." : "Få tilgang til nettstedet usikkert via HTTP. Du er sterkt anbefalt å sette opp serveren din for å kreve HTTPS i stedet, som beskrevet i<a href=\"{docUrl}\">tips for bedre sikkerhet ↗</a>.", "Shared" : "Delt", @@ -154,6 +157,7 @@ "Choose a password for the public link" : "Velg et passord for den offentlige lenken", "Choose a password for the public link or press the \"Enter\" key" : "Velg et passord for den offentlige lenken eller trykk \"Enter\"-tasten", "Copied!" : "Kopiert!", + "Copy link" : "Kopier lenke", "Not supported!" : "Ikke støttet!", "Press ⌘-C to copy." : "Trykk ⌘-C for å kopiere", "Press Ctrl-C to copy." : "Trykk Ctrl-C for å kopiere", @@ -171,11 +175,14 @@ "Expiration" : "Utløpsdato", "Expiration date" : "Utløpsdato", "Note to recipient" : "Note til mottaker", + "Unshare" : "Avslutt deling", "Share link" : "Del lenke", - "Enable" : "Aktiver", + "Password protect by Talk" : "Passord beskyttet av Talk", + "Could not unshare" : "Kunne ikke avslutte deling", "Shared with you and the group {group} by {owner}" : "Delt med deg og gruppen {group} av {owner}", "Shared with you and {circle} by {owner}" : "Delt med deg og {circle} av {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Delt med deg og samtalen {conversation} av {owner}", + "Shared with you in a conversation by {owner}" : "Delt md deg i samtale med {owner}", "Shared with you by {owner}" : "Delt med deg av {owner}", "Choose a password for the mail share" : "Velg et passord for e-postlageret", "group" : "gruppe", @@ -184,15 +191,13 @@ "email" : "e-post", "conversation" : "samtale", "shared by {sharer}" : "delt av {sharer}", - "Unshare" : "Avslutt deling", "Can reshare" : "Kan dele videre", "Can edit" : "Kan redigere", "Can create" : "Kan opprette", "Can change" : "Kan endre", "Can delete" : "Kan slette", - "Password protect by Talk" : "Passord beskyttet av Talk", "Access control" : "Tilgangskontroll", - "Could not unshare" : "Kunne ikke avslutte deling", + "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} delt via lenke", "Error while sharing" : "Feil under deling", "Share details could not be loaded for this item." : "Klarte ikke å laste inn detaljer om deling for dette elementet.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Minst {count} tegn er nødvendig for autofullføring","Minst {count} antall tegn er nødvendig for autofullføring"], @@ -201,12 +206,8 @@ "No users found for {search}" : "Ingen brukere funnet for {search}", "An error occurred (\"{message}\"). Please try again" : "En feil inntraff (\"{message}\"). Prøv igjen", "An error occurred. Please try again" : "Det oppstod en feil. Prøv igjen", - "{sharee} (group)" : "{sharee} (gruppe)", - "{sharee} (remote)" : "{sharee} (ekstern)", "{sharee} (remote group)" : "{sharee} (remote group)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", "Share" : "Del", "Name or email address..." : "Navn eller e-postadresse…", "Name or federated cloud ID..." : "Navn eller sammenknyttet sky-ID…", @@ -248,6 +249,8 @@ "Help" : "Hjelp", "Access forbidden" : "Tilgang nektet", "File not found" : "Finner ikke filen", + "The document could not be found on the server. Maybe the share was deleted or has expired?" : "Dokumentasjon kan ikke finnes på server. Er deling slettet eller utløpt?", + "Back to %s" : "Tilbake til %s", "Internal Server Error" : "Intern tjenerfeil.", "The server was unable to complete your request." : "Tjeneren kunne ikke fullføre din forespørsel.", "If this happens again, please send the technical details below to the server administrator." : "Hvis dette skjer igjen, send de tekniske detaljene nedenfor til tjeneradministratoren.", @@ -309,23 +312,30 @@ "Forgot password?" : "Glemt passord?", "Back to login" : "Tilbake til innlogging", "Connect to your account" : "Koble til kontoen din", + "Please log in before granting %1$s access to your %2$s account." : "Logg inn før du tildeler %1$stilgang til din %2$skonto.", "App token" : "Program-symbol", "Grant access" : "Gi tilgang", "Alternative log in using app token" : "Alternativ logg inn ved hjelp av program kode", "Account access" : "Kontotilgang", + "You are about to grant %1$s access to your %2$s account." : "Du er i ferd med å tildele %1$s tilgang til din %2$skonto.", "Redirecting …" : "Videresender…", "New password" : "Nytt passord", "New Password" : "Nytt passord", "This share is password-protected" : "Denne deling er beskyttet med passord", "The password is wrong. Try again." : "Feil passord, forsøk igjen", "Two-factor authentication" : "Tofaktor autentisering", + "Enhanced security is enabled for your account. Choose a second factor for authentication:" : "Utvidet sikkerhet er tilgjengelig fo rdin konto. Velg en to-faktor for autentisering.", "Could not load at least one of your enabled two-factor auth methods. Please contact your admin." : "Kunne ikke laste minst en av de aktiverte tofaktor metodene. Ta kontakt med administrasjonen din.", + "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "To-faktor autentisering er aktivert men er ikke satt opp for din konto. Kontakt administrator for hjelp.", + "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "To-faktor autentisering er aktivert men er ikke satt opp for din konto. Bruk en av dine sikkerhet koder for å logge inn eller kontakt administrator for hjelp.", "Use backup code" : "Bruker sikkerhetskopi kode", "Cancel log in" : "Avbryt innlogging", "Error while validating your second factor" : "Feil under validering av din andre faktor", "Access through untrusted domain" : "Nå gjennom ubetrodd domene", "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." : "Kontakt din administrator. Hvis du er en administrator, sett opp innstillingen \"trusted_domains\" i config/config.php som eksemplet i config/config.sample.php.", + "Further information how to configure this can be found in the %1$sdocumentation%2$s." : "Ytterligere informasojn om oppsett finnes i %1$sdokumentasjon%2$s.", "App update required" : "Program-oppdatering kreves", + "%1$s will be updated to version %2$s" : "%1$soppdateres til versjon %2$s", "These apps will be updated:" : "Disse programmene vil bli oppdatert:", "These incompatible apps will be disabled:" : "Disse ikke-kompatible programmene vil bli deaktivert:", "The theme %s has been disabled." : "Drakten %s har blitt deaktivert.", @@ -338,7 +348,9 @@ "For help, see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation</a>." : "For hjelp, les <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">dokumentasjonen</a>.", "I know that if I continue doing the update via web UI has the risk, that the request runs into a timeout and could cause data loss, but I have a backup and know how to restore my instance in case of a failure." : "Jeg vet at hvis jeg fortsetter oppdateringen via vev-grensesnittet er det en mulighet for datatap som følge av tidsavbrudd, men jeg har en sikkerhetskopi og vet hvordan jeg skal gjenopprette min installasjon hvis den feiler.", "Upgrade via web on my own risk" : "Oppgrader via vev på min egen risikio", + "Maintenance mode" : "Modus for vedlikehold", "This %s instance is currently in maintenance mode, which may take a while." : "Denne %s-instansen er for øyeblikket i vedlikeholdsmodus, noe som kan vare en stund.", + "This page will refresh itself when the instance is available again." : "Siden vil oppdatere seg selv når instans er tilgjengelig igjen.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakt systemadministratoren hvis denne meldingen var uventet eller ikke forsvinner.", "Updated \"%s\" to %s" : "Oppdaterte \"%s\" til %s", "%s (3rdparty)" : "%s (tredjepart)", @@ -362,6 +374,9 @@ "Error setting expiration date" : "Kan ikke sette utløpsdato", "The public link will expire no later than {days} days after it is created" : "Den offentlige lenken vil utløpe senest {days} dager etter at den lages", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delt via lenke", + "{sharee} (group)" : "{sharee} (gruppe)", + "{sharee} (remote)" : "{sharee} (ekstern)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Del med andre ved å skrive inn en bruker, en gruppe, en sammenknyttet sky-ID eller en e-postadresse.", "Share with other people by entering a user or group or a federated cloud ID." : "Del med andre ved å skrive inn en bruker, en gruppe eller en sammenknyttet sky-ID", "Share with other people by entering a user or group or an email address." : "Del med andre ved å skrive inn en bruker, en gruppe, eller en e-postadresse.", @@ -392,6 +407,9 @@ "Back to log in" : "Tilbake til innlogging", "You are about to grant %s access to your %s account." : "Du er i ferd med å gi %s tilgang til din %s konto.", "Depending on your configuration, this button could also work to trust the domain:" : "Avhengig av ditt oppsett, kan denne knappen også betro domenet.", + "Copy URL" : "Kopier URL", + "Enable" : "Aktiver", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : "Logg inn før du innvilger %s tilgang til din %s konto.", "Further information how to configure this can be found in the %sdocumentation%s." : "Ytterligere informasjon om hvordan du konfigurerer dette kan du finne i %sdokumentasjon%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/nl.js b/core/l10n/nl.js index e79ab4ab6a8..57e2578b875 100644 --- a/core/l10n/nl.js +++ b/core/l10n/nl.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Onderhoudsmodus ingeschakeld", "Turned off maintenance mode" : "Onderhoudsmodus uitgeschakeld", "Maintenance mode is kept active" : "Onderhoudsmodus blijft actief", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Wachten op gereedmelding cron (over 5 seconden nieuwe check) …", "Updating database schema" : "Databaseschema aan het bijwerken", "Updated database" : "Database bijgewerkt", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Controleert of het databaseschema geüpdatet kan worden (dit kan lang duren afhankelijk van de grootte van de de database)", @@ -160,13 +159,14 @@ OC.L10N.register( "Choose a password for the public link" : "Kies een wachtwoord voor de openbare link", "Choose a password for the public link or press the \"Enter\" key" : "Kies een wachtwoord voor de openbare link of druk op \"Enter\"", "Copied!" : "Gekopieerd!", + "Copy link" : "Kopiëren link ", "Not supported!" : "Niet ondersteund!", "Press ⌘-C to copy." : "Druk op ⌘-C om te kopiëren.", "Press Ctrl-C to copy." : "Druk op Ctrl-C om te kopiëren.", "Resharing is not allowed" : "Verder delen is niet toegestaan", "Share to {name}" : "Delen naar {name}", - "Copy link" : "Kopiëren link ", "Link" : "Link", + "Hide download" : "Verberg download", "Password protect" : "Wachtwoord beveiligd", "Allow editing" : "Bewerken toestaan", "Email link to person" : "Email-link naar persoon", @@ -178,8 +178,10 @@ OC.L10N.register( "Expiration" : "Vervaltermijn", "Expiration date" : "Vervaldatum", "Note to recipient" : "Notitie voor ontvanger", + "Unshare" : "Delen stoppen", "Share link" : "Deellink", - "Enable" : "Inschakelen", + "Password protect by Talk" : "Wachtwoord beveiligd door Talk", + "Could not unshare" : "Kon delen niet ongedaan maken", "Shared with you and the group {group} by {owner}" : "Met jou en de groep {group} gedeeld door {owner}", "Shared with you and {circle} by {owner}" : "Gedeeld met jou en {circle} door {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Gedeeld met jou en gesprek {conversation} door {owner}", @@ -192,16 +194,13 @@ OC.L10N.register( "email" : "email", "conversation" : "gesprek", "shared by {sharer}" : "Gedeeld door {eigenaar}", - "Unshare" : "Delen stoppen", "Can reshare" : "Kan doordelen", "Can edit" : "Kan bewerken", "Can create" : "Kan creëren", "Can change" : "Kan wijzigen", "Can delete" : "Kan verwijderen", - "Password protect by Talk" : "Wachtwoord beveiligd door Talk", "Access control" : "Toegangscontrole", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} gedeeld via link", - "Could not unshare" : "Kon delen niet ongedaan maken", "Error while sharing" : "Fout tijdens het delen", "Share details could not be loaded for this item." : "Deel details van dit object kon niet worden geladen.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Minimaal {count} karakter benodigd voor automatisch aanvullen","Minimaal {count} karakters benodigd voor automatisch aanvullen"], @@ -210,12 +209,9 @@ OC.L10N.register( "No users found for {search}" : "Geen gebruikers gevonden voor {search}", "An error occurred (\"{message}\"). Please try again" : "Er heeft zich een fout voorgedaan (\"{message}\"). Probeer het opnieuw", "An error occurred. Please try again" : "Er trad een fout op. Probeer het opnieuw", - "{sharee} (group)" : "{sharee} (groep)", - "{sharee} (remote)" : "{sharee} (extern)", "{sharee} (remote group)" : "{sharee} (remote group)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (gesprek)", + "Other" : "Ander", "Share" : "Delen", "Name or email address..." : "Naam of emailadres...", "Name or federated cloud ID..." : "Naam of gefedereerd Cloud ID:", @@ -301,6 +297,7 @@ OC.L10N.register( "Skip to main content" : "Ga naar hoofdinhoud", "Skip to navigation of app" : "Ga naar navigatie van app", "More apps" : "Meer apps", + "More" : "Meer", "More apps menu" : "Meer apps menu", "Search" : "Zoeken", "Reset search" : "Zoekopdracht wissen", @@ -382,6 +379,9 @@ OC.L10N.register( "Error setting expiration date" : "Fout tijdens het instellen van de vervaldatum", "The public link will expire no later than {days} days after it is created" : "De openbare link vervalt niet eerder dan {days} dagen na het aanmaken", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delen via link", + "{sharee} (group)" : "{sharee} (groep)", + "{sharee} (remote)" : "{sharee} (extern)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Deel met anderen door het invullen van een gebruiker, groep, gefedereerd cloud ID of een emailadres.", "Share with other people by entering a user or group or a federated cloud ID." : "Deel met anderen door middel van gebruikers, groep of een gefedereerd cloud ID.", "Share with other people by entering a user or group or an email address." : "Deel met anderen door het invullen van een gebruiker, groep of een emailadres.", @@ -413,6 +413,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Je staat op het punt om %s toegang te verlenen to je %s account.", "Depending on your configuration, this button could also work to trust the domain:" : "Afhankelijk van je configuratie kan deze knop ook werken om het volgende domein te vertrouwen:", "Copy URL" : "Kopiëren URL", + "Enable" : "Inschakelen", + "{sharee} (conversation)" : "{sharee} (gesprek)", "Please log in before granting %s access to your %s account." : "Log alsjeblieft in voordat je %s toegang geeft tot je %s account.", "Further information how to configure this can be found in the %sdocumentation%s." : "Verdere informatie over hoe je dit insteld staat in de %s documentatie %s." }, diff --git a/core/l10n/nl.json b/core/l10n/nl.json index f4b753fe016..e987cdd5f7c 100644 --- a/core/l10n/nl.json +++ b/core/l10n/nl.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Onderhoudsmodus ingeschakeld", "Turned off maintenance mode" : "Onderhoudsmodus uitgeschakeld", "Maintenance mode is kept active" : "Onderhoudsmodus blijft actief", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Wachten op gereedmelding cron (over 5 seconden nieuwe check) …", "Updating database schema" : "Databaseschema aan het bijwerken", "Updated database" : "Database bijgewerkt", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Controleert of het databaseschema geüpdatet kan worden (dit kan lang duren afhankelijk van de grootte van de de database)", @@ -158,13 +157,14 @@ "Choose a password for the public link" : "Kies een wachtwoord voor de openbare link", "Choose a password for the public link or press the \"Enter\" key" : "Kies een wachtwoord voor de openbare link of druk op \"Enter\"", "Copied!" : "Gekopieerd!", + "Copy link" : "Kopiëren link ", "Not supported!" : "Niet ondersteund!", "Press ⌘-C to copy." : "Druk op ⌘-C om te kopiëren.", "Press Ctrl-C to copy." : "Druk op Ctrl-C om te kopiëren.", "Resharing is not allowed" : "Verder delen is niet toegestaan", "Share to {name}" : "Delen naar {name}", - "Copy link" : "Kopiëren link ", "Link" : "Link", + "Hide download" : "Verberg download", "Password protect" : "Wachtwoord beveiligd", "Allow editing" : "Bewerken toestaan", "Email link to person" : "Email-link naar persoon", @@ -176,8 +176,10 @@ "Expiration" : "Vervaltermijn", "Expiration date" : "Vervaldatum", "Note to recipient" : "Notitie voor ontvanger", + "Unshare" : "Delen stoppen", "Share link" : "Deellink", - "Enable" : "Inschakelen", + "Password protect by Talk" : "Wachtwoord beveiligd door Talk", + "Could not unshare" : "Kon delen niet ongedaan maken", "Shared with you and the group {group} by {owner}" : "Met jou en de groep {group} gedeeld door {owner}", "Shared with you and {circle} by {owner}" : "Gedeeld met jou en {circle} door {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Gedeeld met jou en gesprek {conversation} door {owner}", @@ -190,16 +192,13 @@ "email" : "email", "conversation" : "gesprek", "shared by {sharer}" : "Gedeeld door {eigenaar}", - "Unshare" : "Delen stoppen", "Can reshare" : "Kan doordelen", "Can edit" : "Kan bewerken", "Can create" : "Kan creëren", "Can change" : "Kan wijzigen", "Can delete" : "Kan verwijderen", - "Password protect by Talk" : "Wachtwoord beveiligd door Talk", "Access control" : "Toegangscontrole", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} gedeeld via link", - "Could not unshare" : "Kon delen niet ongedaan maken", "Error while sharing" : "Fout tijdens het delen", "Share details could not be loaded for this item." : "Deel details van dit object kon niet worden geladen.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Minimaal {count} karakter benodigd voor automatisch aanvullen","Minimaal {count} karakters benodigd voor automatisch aanvullen"], @@ -208,12 +207,9 @@ "No users found for {search}" : "Geen gebruikers gevonden voor {search}", "An error occurred (\"{message}\"). Please try again" : "Er heeft zich een fout voorgedaan (\"{message}\"). Probeer het opnieuw", "An error occurred. Please try again" : "Er trad een fout op. Probeer het opnieuw", - "{sharee} (group)" : "{sharee} (groep)", - "{sharee} (remote)" : "{sharee} (extern)", "{sharee} (remote group)" : "{sharee} (remote group)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (gesprek)", + "Other" : "Ander", "Share" : "Delen", "Name or email address..." : "Naam of emailadres...", "Name or federated cloud ID..." : "Naam of gefedereerd Cloud ID:", @@ -299,6 +295,7 @@ "Skip to main content" : "Ga naar hoofdinhoud", "Skip to navigation of app" : "Ga naar navigatie van app", "More apps" : "Meer apps", + "More" : "Meer", "More apps menu" : "Meer apps menu", "Search" : "Zoeken", "Reset search" : "Zoekopdracht wissen", @@ -380,6 +377,9 @@ "Error setting expiration date" : "Fout tijdens het instellen van de vervaldatum", "The public link will expire no later than {days} days after it is created" : "De openbare link vervalt niet eerder dan {days} dagen na het aanmaken", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delen via link", + "{sharee} (group)" : "{sharee} (groep)", + "{sharee} (remote)" : "{sharee} (extern)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Deel met anderen door het invullen van een gebruiker, groep, gefedereerd cloud ID of een emailadres.", "Share with other people by entering a user or group or a federated cloud ID." : "Deel met anderen door middel van gebruikers, groep of een gefedereerd cloud ID.", "Share with other people by entering a user or group or an email address." : "Deel met anderen door het invullen van een gebruiker, groep of een emailadres.", @@ -411,6 +411,8 @@ "You are about to grant %s access to your %s account." : "Je staat op het punt om %s toegang te verlenen to je %s account.", "Depending on your configuration, this button could also work to trust the domain:" : "Afhankelijk van je configuratie kan deze knop ook werken om het volgende domein te vertrouwen:", "Copy URL" : "Kopiëren URL", + "Enable" : "Inschakelen", + "{sharee} (conversation)" : "{sharee} (gesprek)", "Please log in before granting %s access to your %s account." : "Log alsjeblieft in voordat je %s toegang geeft tot je %s account.", "Further information how to configure this can be found in the %sdocumentation%s." : "Verdere informatie over hoe je dit insteld staat in de %s documentatie %s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/pl.js b/core/l10n/pl.js index c74cda973e7..d667c8bee64 100644 --- a/core/l10n/pl.js +++ b/core/l10n/pl.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Włączony tryb konserwacji", "Turned off maintenance mode" : "Wyłączony tryb konserwacji", "Maintenance mode is kept active" : "Tryb konserwacji pozostaje aktywny", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Oczekiwanie na zakończenie zadania cron (ponowne sprawdzenie w ciągu 5 sekund) ...", "Updating database schema" : "Aktualizacja struktury bazy danych", "Updated database" : "Zaktualizuj bazę", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Sprawdzam czy struktura bazy danych może zostać zaktualizowana (to może zająć sporo czasu i zależy od rozmiaru bazy danych)", @@ -157,12 +156,12 @@ OC.L10N.register( "Choose a password for the public link" : "Wybierz hasło dla linku publicznego", "Choose a password for the public link or press the \"Enter\" key" : "Wybierz hasło dla publicznego linka lub wciśnij klawisz \"Enter\"", "Copied!" : "Skopiowano!", + "Copy link" : "Skopiuj link", "Not supported!" : "Brak wsparcia!", "Press ⌘-C to copy." : "Wciśnij ⌘-C by skopiować.", "Press Ctrl-C to copy." : "Wciśnij Ctrl-C by skopiować,", "Resharing is not allowed" : "Współdzielenie nie jest możliwe", "Share to {name}" : "Wspóldziel z {name}", - "Copy link" : "Skopiuj link", "Link" : "Odnośnik", "Password protect" : "Zabezpiecz hasłem", "Allow editing" : "Pozwól na edycję", @@ -175,8 +174,10 @@ OC.L10N.register( "Expiration" : "Wygaśnięcie", "Expiration date" : "Data wygaśnięcia", "Note to recipient" : "Notatka dla odbiorcy", + "Unshare" : "Zatrzymaj współdzielenie", "Share link" : "Udostępnij link", - "Enable" : "Włącz", + "Password protect by Talk" : "Ochronę hasłem zapewnia Talk", + "Could not unshare" : "Nie udało się usunąć udostępnienia", "Shared with you and the group {group} by {owner}" : "Udostępnione tobie i grupie {group} przez {owner}", "Shared with you and {circle} by {owner}" : "Współdzielone z Tobą i {circle} przez {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Współdzielone z Tobą i konwersacją {conversation} przez {owner}", @@ -187,17 +188,14 @@ OC.L10N.register( "remote" : "zdalny", "remote group" : "zdalna grupa", "email" : "email", - "conversation" : "konwersacja", + "conversation" : "rozmowa", "shared by {sharer}" : "współdzielone przez {sharer}", - "Unshare" : "Zatrzymaj współdzielenie", "Can reshare" : "Może współdzielić z innymi", "Can edit" : "Może edytować", "Can create" : "Może tworzyć", "Can change" : "Może zmieniać", "Can delete" : "Może usuwać", - "Password protect by Talk" : "Ochronę hasłem zapewnia Talk", "Access control" : "Kontrola dostępu", - "Could not unshare" : "Nie udało się usunąć udostępnienia", "Error while sharing" : "Błąd podczas udostępniania", "Share details could not be loaded for this item." : "Szczegóły udziału nie mogły zostać wczytane dla tego obiektu.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Do automatycznego uzupełnienia potrzebny jest co najmniej {count} znak","Do automatycznego uzupełnienia potrzebnych jest co najmniej {count} znaków","Do automatycznego uzupełnienia potrzebnych jest co najmniej {count} znaków","Do automatycznego uzupełnienia potrzebnych jest co najmniej {count} znaków"], @@ -206,12 +204,8 @@ OC.L10N.register( "No users found for {search}" : "Nie znaleziono użytkowników dla {search}", "An error occurred (\"{message}\"). Please try again" : "Wystąpił błąd (\"{message}\"). Spróbuj ponownie", "An error occurred. Please try again" : "Wystąpił błąd. Proszę spróbować ponownie.", - "{sharee} (group)" : "{sharee} (grupa)", - "{sharee} (remote)" : "{sharee} (zdalny)", "{sharee} (remote group)" : "{sharee} (zdalna grupa)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (konwersacja)", "Share" : "Udostępnij", "Name or email address..." : "Nazwa lub adres e-mail…", "Name or federated cloud ID..." : "Nazwa lub ID chmury stowarzyszonej…", @@ -370,6 +364,9 @@ OC.L10N.register( "Error setting expiration date" : "Błąd podczas ustawiania daty wygaśnięcia", "The public link will expire no later than {days} days after it is created" : "Link publiczny wygaśnie nie później niż po {days} dniach od utworzenia", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} udostępniane za pośrednictwem łącza", + "{sharee} (group)" : "{sharee} (grupa)", + "{sharee} (remote)" : "{sharee} (zdalny)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Współdziel z innymi osobami przez wpisanie użytkownika lub grupy, ID chmury stowarzyszonej lub adres e-mail.", "Share with other people by entering a user or group or a federated cloud ID." : "Współdziel z innymi osobami przez wpisanie użytkownika lub grupy lub ID chmury stowarzyszonej.", "Share with other people by entering a user or group or an email address." : "Współdziel z innymi osobami przez wpisanie użytkownika lub grupy lub adresu e-mail.", @@ -401,6 +398,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Zamierzasz udzielić %s dostępu do Twojego konta %s.", "Depending on your configuration, this button could also work to trust the domain:" : "W zależności od Twojej konfiguracji, ten przycisk aby zaufać domenie powinien również zadziałać: ", "Copy URL" : "Skopiuj URL", + "Enable" : "Włącz", + "{sharee} (conversation)" : "{sharee} (konwersacja)", "Please log in before granting %s access to your %s account." : "Zaloguj się aby udzielić %s dostępu do Twojego konta %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Więcej informacji o konfiguracji znajdziesz w %sdokumentacji%s." }, diff --git a/core/l10n/pl.json b/core/l10n/pl.json index f62f1ee31f6..271348c8a3d 100644 --- a/core/l10n/pl.json +++ b/core/l10n/pl.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Włączony tryb konserwacji", "Turned off maintenance mode" : "Wyłączony tryb konserwacji", "Maintenance mode is kept active" : "Tryb konserwacji pozostaje aktywny", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Oczekiwanie na zakończenie zadania cron (ponowne sprawdzenie w ciągu 5 sekund) ...", "Updating database schema" : "Aktualizacja struktury bazy danych", "Updated database" : "Zaktualizuj bazę", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Sprawdzam czy struktura bazy danych może zostać zaktualizowana (to może zająć sporo czasu i zależy od rozmiaru bazy danych)", @@ -155,12 +154,12 @@ "Choose a password for the public link" : "Wybierz hasło dla linku publicznego", "Choose a password for the public link or press the \"Enter\" key" : "Wybierz hasło dla publicznego linka lub wciśnij klawisz \"Enter\"", "Copied!" : "Skopiowano!", + "Copy link" : "Skopiuj link", "Not supported!" : "Brak wsparcia!", "Press ⌘-C to copy." : "Wciśnij ⌘-C by skopiować.", "Press Ctrl-C to copy." : "Wciśnij Ctrl-C by skopiować,", "Resharing is not allowed" : "Współdzielenie nie jest możliwe", "Share to {name}" : "Wspóldziel z {name}", - "Copy link" : "Skopiuj link", "Link" : "Odnośnik", "Password protect" : "Zabezpiecz hasłem", "Allow editing" : "Pozwól na edycję", @@ -173,8 +172,10 @@ "Expiration" : "Wygaśnięcie", "Expiration date" : "Data wygaśnięcia", "Note to recipient" : "Notatka dla odbiorcy", + "Unshare" : "Zatrzymaj współdzielenie", "Share link" : "Udostępnij link", - "Enable" : "Włącz", + "Password protect by Talk" : "Ochronę hasłem zapewnia Talk", + "Could not unshare" : "Nie udało się usunąć udostępnienia", "Shared with you and the group {group} by {owner}" : "Udostępnione tobie i grupie {group} przez {owner}", "Shared with you and {circle} by {owner}" : "Współdzielone z Tobą i {circle} przez {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Współdzielone z Tobą i konwersacją {conversation} przez {owner}", @@ -185,17 +186,14 @@ "remote" : "zdalny", "remote group" : "zdalna grupa", "email" : "email", - "conversation" : "konwersacja", + "conversation" : "rozmowa", "shared by {sharer}" : "współdzielone przez {sharer}", - "Unshare" : "Zatrzymaj współdzielenie", "Can reshare" : "Może współdzielić z innymi", "Can edit" : "Może edytować", "Can create" : "Może tworzyć", "Can change" : "Może zmieniać", "Can delete" : "Może usuwać", - "Password protect by Talk" : "Ochronę hasłem zapewnia Talk", "Access control" : "Kontrola dostępu", - "Could not unshare" : "Nie udało się usunąć udostępnienia", "Error while sharing" : "Błąd podczas udostępniania", "Share details could not be loaded for this item." : "Szczegóły udziału nie mogły zostać wczytane dla tego obiektu.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Do automatycznego uzupełnienia potrzebny jest co najmniej {count} znak","Do automatycznego uzupełnienia potrzebnych jest co najmniej {count} znaków","Do automatycznego uzupełnienia potrzebnych jest co najmniej {count} znaków","Do automatycznego uzupełnienia potrzebnych jest co najmniej {count} znaków"], @@ -204,12 +202,8 @@ "No users found for {search}" : "Nie znaleziono użytkowników dla {search}", "An error occurred (\"{message}\"). Please try again" : "Wystąpił błąd (\"{message}\"). Spróbuj ponownie", "An error occurred. Please try again" : "Wystąpił błąd. Proszę spróbować ponownie.", - "{sharee} (group)" : "{sharee} (grupa)", - "{sharee} (remote)" : "{sharee} (zdalny)", "{sharee} (remote group)" : "{sharee} (zdalna grupa)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (konwersacja)", "Share" : "Udostępnij", "Name or email address..." : "Nazwa lub adres e-mail…", "Name or federated cloud ID..." : "Nazwa lub ID chmury stowarzyszonej…", @@ -368,6 +362,9 @@ "Error setting expiration date" : "Błąd podczas ustawiania daty wygaśnięcia", "The public link will expire no later than {days} days after it is created" : "Link publiczny wygaśnie nie później niż po {days} dniach od utworzenia", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} udostępniane za pośrednictwem łącza", + "{sharee} (group)" : "{sharee} (grupa)", + "{sharee} (remote)" : "{sharee} (zdalny)", + "{sharee} (email)" : "{sharee} (e-mail)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Współdziel z innymi osobami przez wpisanie użytkownika lub grupy, ID chmury stowarzyszonej lub adres e-mail.", "Share with other people by entering a user or group or a federated cloud ID." : "Współdziel z innymi osobami przez wpisanie użytkownika lub grupy lub ID chmury stowarzyszonej.", "Share with other people by entering a user or group or an email address." : "Współdziel z innymi osobami przez wpisanie użytkownika lub grupy lub adresu e-mail.", @@ -399,6 +396,8 @@ "You are about to grant %s access to your %s account." : "Zamierzasz udzielić %s dostępu do Twojego konta %s.", "Depending on your configuration, this button could also work to trust the domain:" : "W zależności od Twojej konfiguracji, ten przycisk aby zaufać domenie powinien również zadziałać: ", "Copy URL" : "Skopiuj URL", + "Enable" : "Włącz", + "{sharee} (conversation)" : "{sharee} (konwersacja)", "Please log in before granting %s access to your %s account." : "Zaloguj się aby udzielić %s dostępu do Twojego konta %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Więcej informacji o konfiguracji znajdziesz w %sdokumentacji%s." },"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);" diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index a797647db5d..8ded4df100f 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Ativar o modo de manutenção", "Turned off maintenance mode" : "Desativar o modo de manutenção", "Maintenance mode is kept active" : "O modo de manutenção está sendo mantido como ativo", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Aguardando o cron terminar (verificando de novo em 5 segundos)…", "Updating database schema" : "Atualizando o schema do banco de dados", "Updated database" : "Atualizar o banco de dados", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Verificando se o schema do banco de dados pode ser atualizado (isso pode levar muito tempo, dependendo do tamanho do banco de dados)", @@ -160,13 +159,17 @@ OC.L10N.register( "Choose a password for the public link" : "Escolha uma senha", "Choose a password for the public link or press the \"Enter\" key" : "Escolha uma senha", "Copied!" : "Copiado!", + "Copy link" : "Copiar link", "Not supported!" : "Não suportado!", "Press ⌘-C to copy." : "Pressione ⌘-C para copiar.", "Press Ctrl-C to copy." : "Pressione Ctrl-C para copiar.", + "Unable to create a link share" : "Não é possível criar um compartilhamento por link", + "Unable to toggle this option" : "Não é possível alternar esta opção", "Resharing is not allowed" : "Não é permitido recompartilhar", "Share to {name}" : "Compartilhar com {name}", - "Copy link" : "Copiar link", "Link" : "Link", + "Hide download" : "Ocultar download", + "Password protection enforced" : "Proteção por senha aplicada", "Password protect" : "Proteger com senha", "Allow editing" : "Permitir edição", "Email link to person" : "Enviar link por e-mail", @@ -174,12 +177,19 @@ OC.L10N.register( "Allow upload and editing" : "Permitir envio e edição", "Read only" : "Somente leitura", "File drop (upload only)" : "Zona de arquivos (somente envio)", + "Expiration date enforced" : "Data de expiração aplicada", "Set expiration date" : "Definir data de expiração", "Expiration" : "Expiração", "Expiration date" : "Data de expiração", "Note to recipient" : "Nota para o destinatário", + "Unshare" : "Descompartilhar", + "Delete share link" : "Excluir link de compartilhamento", + "Add another link" : "Adicionar outro link", + "Password protection for links is mandatory" : "A proteção por senha para links é obrigatória", "Share link" : "Compartilhar link", - "Enable" : "Ativar", + "New share link" : "Novo link de compartilhamento", + "Password protect by Talk" : "Senha protegida pelo Talk", + "Could not unshare" : "Não foi possível descompartilhar", "Shared with you and the group {group} by {owner}" : "Compartilhado com você e com o grupo {group} por {owner}", "Shared with you and {circle} by {owner}" : "Compartilhado com você e {circle} por {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Compartilhado com você e a conversa {conversation} por {owner}", @@ -192,16 +202,13 @@ OC.L10N.register( "email" : "e-mail", "conversation" : "Conversa", "shared by {sharer}" : "compartilhado por {sharer}", - "Unshare" : "Descompartilhar", "Can reshare" : "Pode compartilhar novamente", "Can edit" : "Pode editar", "Can create" : "Pode criar", "Can change" : "Pode modificar", "Can delete" : "Pode excluir", - "Password protect by Talk" : "Senha protegida pelo Talk", "Access control" : "Controle de acesso", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} compartilhou por link", - "Could not unshare" : "Não foi possível descompartilhar", "Error while sharing" : "Erro ao compartilhar", "Share details could not be loaded for this item." : "Detalhes de compartilhamento não puderam ser carregados para este item.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Pelo menos {count} caractere é necessário para completar automaticamente","Pelo menos {count} caracteres são necessários para completar automaticamente"], @@ -210,12 +217,10 @@ OC.L10N.register( "No users found for {search}" : "Nenhum usuário encontrado para {search}", "An error occurred (\"{message}\"). Please try again" : "Ocorreu um erro (\"{message}\"). Tente novamente", "An error occurred. Please try again" : "Ocorreu um erro. Tente novamente", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", "{sharee} (remote group)" : "{sharee} (grupo remoto)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Home", + "Other" : "Outro", "Share" : "Compartilhar", "Name or email address..." : "Nome ou endereço de e-mail...", "Name or federated cloud ID..." : "Nome ou ID de cloud federada...", @@ -301,6 +306,7 @@ OC.L10N.register( "Skip to main content" : "Ir ao conteúdo principal", "Skip to navigation of app" : "Ir à navegação do aplicativo", "More apps" : "Mais aplicativos", + "More" : "Mais", "More apps menu" : "Mais aplicativos", "Search" : "Pesquisar", "Reset search" : "Redefinir pesquisa", @@ -382,6 +388,9 @@ OC.L10N.register( "Error setting expiration date" : "Erro ao definir data de expiração", "The public link will expire no later than {days} days after it is created" : "O link público irá expirar não antes de {days} depois de criado", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatiorDisplayName}} compartilhou via link", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (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 e-mail.", "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.", @@ -413,6 +422,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Você está prestes a conceder acesso a %s à sua conta %s.", "Depending on your configuration, this button could also work to trust the domain:" : "Dependendo de sua configuração, este botão também pode funcionar para confiar no domínio.", "Copy URL" : "Copiar URL", + "Enable" : "Ativar", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : " Por favor, faça o login antes de conceder %s acesso à sua %s conta.", "Further information how to configure this can be found in the %sdocumentation%s." : "Mais informações sobre configuração podem ser encontradas na %sdocumentação%s." }, diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 319e7368521..a625b363842 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Ativar o modo de manutenção", "Turned off maintenance mode" : "Desativar o modo de manutenção", "Maintenance mode is kept active" : "O modo de manutenção está sendo mantido como ativo", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Aguardando o cron terminar (verificando de novo em 5 segundos)…", "Updating database schema" : "Atualizando o schema do banco de dados", "Updated database" : "Atualizar o banco de dados", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Verificando se o schema do banco de dados pode ser atualizado (isso pode levar muito tempo, dependendo do tamanho do banco de dados)", @@ -158,13 +157,17 @@ "Choose a password for the public link" : "Escolha uma senha", "Choose a password for the public link or press the \"Enter\" key" : "Escolha uma senha", "Copied!" : "Copiado!", + "Copy link" : "Copiar link", "Not supported!" : "Não suportado!", "Press ⌘-C to copy." : "Pressione ⌘-C para copiar.", "Press Ctrl-C to copy." : "Pressione Ctrl-C para copiar.", + "Unable to create a link share" : "Não é possível criar um compartilhamento por link", + "Unable to toggle this option" : "Não é possível alternar esta opção", "Resharing is not allowed" : "Não é permitido recompartilhar", "Share to {name}" : "Compartilhar com {name}", - "Copy link" : "Copiar link", "Link" : "Link", + "Hide download" : "Ocultar download", + "Password protection enforced" : "Proteção por senha aplicada", "Password protect" : "Proteger com senha", "Allow editing" : "Permitir edição", "Email link to person" : "Enviar link por e-mail", @@ -172,12 +175,19 @@ "Allow upload and editing" : "Permitir envio e edição", "Read only" : "Somente leitura", "File drop (upload only)" : "Zona de arquivos (somente envio)", + "Expiration date enforced" : "Data de expiração aplicada", "Set expiration date" : "Definir data de expiração", "Expiration" : "Expiração", "Expiration date" : "Data de expiração", "Note to recipient" : "Nota para o destinatário", + "Unshare" : "Descompartilhar", + "Delete share link" : "Excluir link de compartilhamento", + "Add another link" : "Adicionar outro link", + "Password protection for links is mandatory" : "A proteção por senha para links é obrigatória", "Share link" : "Compartilhar link", - "Enable" : "Ativar", + "New share link" : "Novo link de compartilhamento", + "Password protect by Talk" : "Senha protegida pelo Talk", + "Could not unshare" : "Não foi possível descompartilhar", "Shared with you and the group {group} by {owner}" : "Compartilhado com você e com o grupo {group} por {owner}", "Shared with you and {circle} by {owner}" : "Compartilhado com você e {circle} por {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Compartilhado com você e a conversa {conversation} por {owner}", @@ -190,16 +200,13 @@ "email" : "e-mail", "conversation" : "Conversa", "shared by {sharer}" : "compartilhado por {sharer}", - "Unshare" : "Descompartilhar", "Can reshare" : "Pode compartilhar novamente", "Can edit" : "Pode editar", "Can create" : "Pode criar", "Can change" : "Pode modificar", "Can delete" : "Pode excluir", - "Password protect by Talk" : "Senha protegida pelo Talk", "Access control" : "Controle de acesso", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} compartilhou por link", - "Could not unshare" : "Não foi possível descompartilhar", "Error while sharing" : "Erro ao compartilhar", "Share details could not be loaded for this item." : "Detalhes de compartilhamento não puderam ser carregados para este item.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Pelo menos {count} caractere é necessário para completar automaticamente","Pelo menos {count} caracteres são necessários para completar automaticamente"], @@ -208,12 +215,10 @@ "No users found for {search}" : "Nenhum usuário encontrado para {search}", "An error occurred (\"{message}\"). Please try again" : "Ocorreu um erro (\"{message}\"). Tente novamente", "An error occurred. Please try again" : "Ocorreu um erro. Tente novamente", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", "{sharee} (remote group)" : "{sharee} (grupo remoto)", - "{sharee} (email)" : "{sharee} (e-mail)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (conversation)", + "Home" : "Home", + "Other" : "Outro", "Share" : "Compartilhar", "Name or email address..." : "Nome ou endereço de e-mail...", "Name or federated cloud ID..." : "Nome ou ID de cloud federada...", @@ -299,6 +304,7 @@ "Skip to main content" : "Ir ao conteúdo principal", "Skip to navigation of app" : "Ir à navegação do aplicativo", "More apps" : "Mais aplicativos", + "More" : "Mais", "More apps menu" : "Mais aplicativos", "Search" : "Pesquisar", "Reset search" : "Redefinir pesquisa", @@ -380,6 +386,9 @@ "Error setting expiration date" : "Erro ao definir data de expiração", "The public link will expire no later than {days} days after it is created" : "O link público irá expirar não antes de {days} depois de criado", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatiorDisplayName}} compartilhou via link", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (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 e-mail.", "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.", @@ -411,6 +420,8 @@ "You are about to grant %s access to your %s account." : "Você está prestes a conceder acesso a %s à sua conta %s.", "Depending on your configuration, this button could also work to trust the domain:" : "Dependendo de sua configuração, este botão também pode funcionar para confiar no domínio.", "Copy URL" : "Copiar URL", + "Enable" : "Ativar", + "{sharee} (conversation)" : "{sharee} (conversation)", "Please log in before granting %s access to your %s account." : " Por favor, faça o login antes de conceder %s acesso à sua %s conta.", "Further information how to configure this can be found in the %sdocumentation%s." : "Mais informações sobre configuração podem ser encontradas na %sdocumentação%s." },"pluralForm" :"nplurals=2; plural=(n > 1);" diff --git a/core/l10n/pt_PT.js b/core/l10n/pt_PT.js index 5e6ca82b373..6c574fd14f6 100644 --- a/core/l10n/pt_PT.js +++ b/core/l10n/pt_PT.js @@ -146,7 +146,9 @@ OC.L10N.register( "Set expiration date" : "Definir a data de expiração", "Expiration" : "Expiração", "Expiration date" : "Data de expiração", + "Unshare" : "Cancelar partilha", "Share link" : "Partilhar hiperligação", + "Could not unshare" : "Não foi possível cancelar a partilha", "Shared with you and the group {group} by {owner}" : "Partilhado consigo e com o grupo {group} por {owner}", "Shared with you by {owner}" : "Partilhado consigo por {owner}", "Choose a password for the mail share" : "Escolher senha para a partilha de email", @@ -154,14 +156,12 @@ OC.L10N.register( "remote" : "remoto", "email" : "email", "shared by {sharer}" : "partilhado por {sharer}", - "Unshare" : "Cancelar partilha", "Can reshare" : "Pode partilhar de novo", "Can edit" : "Pode editar", "Can create" : "Pode criar", "Can change" : "Pode alterar", "Can delete" : "Pode apagar", "Access control" : "Controlo de acesso", - "Could not unshare" : "Não foi possível cancelar a partilha", "Error while sharing" : "Erro ao partilhar", "Share details could not be loaded for this item." : "Não foi possível carregar os detalhes de partilha para este item.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Pelo menos {count} caracteres para conclusão automática","At least {count} characters are needed for autocompletion"], @@ -169,9 +169,6 @@ OC.L10N.register( "No users or groups found for {search}" : "Não foram encontrados nenhuns utilizadores ou grupos para {search}", "No users found for {search}" : "Não foram encontrados utilizadores para {search}", "An error occurred. Please try again" : "Ocorreu um erro. Por favor, tente de novo.", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Partilhar", "Name or email address..." : "Nome ou endereço de email...", @@ -315,6 +312,9 @@ OC.L10N.register( "Error setting expiration date" : "Erro ao definir a data de expiração", "The public link will expire no later than {days} days after it is created" : "A hiperligação pública irá expirar, o mais tardar {days} dias depois da sua criação", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} partilhado via ligação", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Partilhar com terceiros introduzindo um nome de utilizador ou grupo, um identificador de federação ou um endereço de e-mail.", "Share with other people by entering a user or group or a federated cloud ID." : "Partilhar com terceiros introduzindo um nome de utilizador ou grupo, um ID de cloud federada ou um endereço de e-mail.", "Share with other people by entering a user or group or an email address." : "Partilhar com terceiros introduzindo um nome de utilizador ou grupo ou um endereço de e-mail.", diff --git a/core/l10n/pt_PT.json b/core/l10n/pt_PT.json index 994cad2f5ca..e80090650a3 100644 --- a/core/l10n/pt_PT.json +++ b/core/l10n/pt_PT.json @@ -144,7 +144,9 @@ "Set expiration date" : "Definir a data de expiração", "Expiration" : "Expiração", "Expiration date" : "Data de expiração", + "Unshare" : "Cancelar partilha", "Share link" : "Partilhar hiperligação", + "Could not unshare" : "Não foi possível cancelar a partilha", "Shared with you and the group {group} by {owner}" : "Partilhado consigo e com o grupo {group} por {owner}", "Shared with you by {owner}" : "Partilhado consigo por {owner}", "Choose a password for the mail share" : "Escolher senha para a partilha de email", @@ -152,14 +154,12 @@ "remote" : "remoto", "email" : "email", "shared by {sharer}" : "partilhado por {sharer}", - "Unshare" : "Cancelar partilha", "Can reshare" : "Pode partilhar de novo", "Can edit" : "Pode editar", "Can create" : "Pode criar", "Can change" : "Pode alterar", "Can delete" : "Pode apagar", "Access control" : "Controlo de acesso", - "Could not unshare" : "Não foi possível cancelar a partilha", "Error while sharing" : "Erro ao partilhar", "Share details could not be loaded for this item." : "Não foi possível carregar os detalhes de partilha para este item.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Pelo menos {count} caracteres para conclusão automática","At least {count} characters are needed for autocompletion"], @@ -167,9 +167,6 @@ "No users or groups found for {search}" : "Não foram encontrados nenhuns utilizadores ou grupos para {search}", "No users found for {search}" : "Não foram encontrados utilizadores para {search}", "An error occurred. Please try again" : "Ocorreu um erro. Por favor, tente de novo.", - "{sharee} (group)" : "{sharee} (grupo)", - "{sharee} (remote)" : "{sharee} (remoto)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Partilhar", "Name or email address..." : "Nome ou endereço de email...", @@ -313,6 +310,9 @@ "Error setting expiration date" : "Erro ao definir a data de expiração", "The public link will expire no later than {days} days after it is created" : "A hiperligação pública irá expirar, o mais tardar {days} dias depois da sua criação", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} partilhado via ligação", + "{sharee} (group)" : "{sharee} (grupo)", + "{sharee} (remote)" : "{sharee} (remoto)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Partilhar com terceiros introduzindo um nome de utilizador ou grupo, um identificador de federação ou um endereço de e-mail.", "Share with other people by entering a user or group or a federated cloud ID." : "Partilhar com terceiros introduzindo um nome de utilizador ou grupo, um ID de cloud federada ou um endereço de e-mail.", "Share with other people by entering a user or group or an email address." : "Partilhar com terceiros introduzindo um nome de utilizador ou grupo ou um endereço de e-mail.", diff --git a/core/l10n/ro.js b/core/l10n/ro.js index aa63b37960c..d9c37969f6b 100644 --- a/core/l10n/ro.js +++ b/core/l10n/ro.js @@ -127,7 +127,9 @@ OC.L10N.register( "Set expiration date" : "Specifică data expirării", "Expiration" : "Expira", "Expiration date" : "Data expirării", + "Unshare" : "Anulare partajare", "Share link" : "Partajează link-ul", + "Could not unshare" : "Nu s-a putut elimina partajarea", "Shared with you and the group {group} by {owner}" : "Distribuie cu tine si grupul {group} de {owner}", "Shared with you by {owner}" : "Distribuie cu tine de {owner}", "Choose a password for the mail share" : "Alege o parolă pentru partajare prin email", @@ -135,14 +137,12 @@ OC.L10N.register( "remote" : "de la distanță", "email" : "email", "shared by {sharer}" : "partajat de {sharer}", - "Unshare" : "Anulare partajare", "Can reshare" : "Poate repartaja", "Can edit" : "Poate edita", "Can create" : "Poate crea", "Can change" : "Poate schimba", "Can delete" : "Poate șterge", "Access control" : "Control acces", - "Could not unshare" : "Nu s-a putut elimina partajarea", "Error while sharing" : "Eroare la partajare", "Share details could not be loaded for this item." : "Nu s-au putut încărca detaliile de partajare pentru acest element.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Este necesar cel puțin un caracter pentru autocompletare","Sunt necesare cel puțin {count} caractere pentru autocompletare","Sunt necesare cel puțin {count} caractere pentru autocompletare"], @@ -150,9 +150,6 @@ OC.L10N.register( "No users or groups found for {search}" : "Nu au fost găsiți utilizatori sau grupuri pentru {search}", "No users found for {search}" : "Nu au fost găsiți utilizatori pentru {search}", "An error occurred. Please try again" : "A apărut o eroare. Încearcă din nou", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (distanță)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Partajează", "Name or email address..." : "Nume sau adresă de email...", @@ -272,6 +269,9 @@ OC.L10N.register( "Error setting expiration date" : "Eroare la specificarea datei de expirare", "The public link will expire no later than {days} days after it is created" : "Legătura publică va expira nu mai târziu de {days} zile de la ziua creării", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} partajat prin legătura", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (distanță)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Partajează cu alte persoane prin introducerea unui utilizator sau grup, a unui ID de cloud federalizat sau a unei adrese de email.", "Share with other people by entering a user or group or a federated cloud ID." : "Partajează cu alte persoane prin introducerea unui utilizator sau grup sau a unui ID de cloud federalizat.", "Share with other people by entering a user or group or an email address." : "Partajează cu alte persoane prin introducerea unui utilizator sau grup sau a unei adrese de email.", diff --git a/core/l10n/ro.json b/core/l10n/ro.json index f6fac2234f5..8bbefd535e4 100644 --- a/core/l10n/ro.json +++ b/core/l10n/ro.json @@ -125,7 +125,9 @@ "Set expiration date" : "Specifică data expirării", "Expiration" : "Expira", "Expiration date" : "Data expirării", + "Unshare" : "Anulare partajare", "Share link" : "Partajează link-ul", + "Could not unshare" : "Nu s-a putut elimina partajarea", "Shared with you and the group {group} by {owner}" : "Distribuie cu tine si grupul {group} de {owner}", "Shared with you by {owner}" : "Distribuie cu tine de {owner}", "Choose a password for the mail share" : "Alege o parolă pentru partajare prin email", @@ -133,14 +135,12 @@ "remote" : "de la distanță", "email" : "email", "shared by {sharer}" : "partajat de {sharer}", - "Unshare" : "Anulare partajare", "Can reshare" : "Poate repartaja", "Can edit" : "Poate edita", "Can create" : "Poate crea", "Can change" : "Poate schimba", "Can delete" : "Poate șterge", "Access control" : "Control acces", - "Could not unshare" : "Nu s-a putut elimina partajarea", "Error while sharing" : "Eroare la partajare", "Share details could not be loaded for this item." : "Nu s-au putut încărca detaliile de partajare pentru acest element.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Este necesar cel puțin un caracter pentru autocompletare","Sunt necesare cel puțin {count} caractere pentru autocompletare","Sunt necesare cel puțin {count} caractere pentru autocompletare"], @@ -148,9 +148,6 @@ "No users or groups found for {search}" : "Nu au fost găsiți utilizatori sau grupuri pentru {search}", "No users found for {search}" : "Nu au fost găsiți utilizatori pentru {search}", "An error occurred. Please try again" : "A apărut o eroare. Încearcă din nou", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (distanță)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Partajează", "Name or email address..." : "Nume sau adresă de email...", @@ -270,6 +267,9 @@ "Error setting expiration date" : "Eroare la specificarea datei de expirare", "The public link will expire no later than {days} days after it is created" : "Legătura publică va expira nu mai târziu de {days} zile de la ziua creării", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} partajat prin legătura", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (distanță)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Partajează cu alte persoane prin introducerea unui utilizator sau grup, a unui ID de cloud federalizat sau a unei adrese de email.", "Share with other people by entering a user or group or a federated cloud ID." : "Partajează cu alte persoane prin introducerea unui utilizator sau grup sau a unui ID de cloud federalizat.", "Share with other people by entering a user or group or an email address." : "Partajează cu alte persoane prin introducerea unui utilizator sau grup sau a unei adrese de email.", diff --git a/core/l10n/ru.js b/core/l10n/ru.js index 5af259d99d1..7bf5e82f0c4 100644 --- a/core/l10n/ru.js +++ b/core/l10n/ru.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Включён режим обслуживания ", "Turned off maintenance mode" : "Отключён режим обслуживания", "Maintenance mode is kept active" : "Режим обслуживания оставлен включенным", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Ожидание завершения работы планировщика (проверка каждые 5 секунд)…", "Updating database schema" : "Выполняется обновление схемы базы данных", "Updated database" : "База данных обновлена", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Проверка возможности обновления схемы базы данных (это может занять длительное время в зависимости от размера базы данных)", @@ -160,12 +159,12 @@ OC.L10N.register( "Choose a password for the public link" : "Укажите пароль для общедоступной ссылки", "Choose a password for the public link or press the \"Enter\" key" : "Укажите пароль для общедоступной ссылки или нажмите «Ввод»", "Copied!" : "Скопировано!", + "Copy link" : "Копировать ссылку", "Not supported!" : "Не поддерживается!", "Press ⌘-C to copy." : "Нажмите ⌘-C для копирования.", "Press Ctrl-C to copy." : "Нажмите Ctrl-C для копирования.", "Resharing is not allowed" : "Повторное открытие доступа запрещено", "Share to {name}" : "Поделиться с {name}", - "Copy link" : "Копировать ссылку", "Link" : "Ссылка", "Password protect" : "Защитить паролем", "Allow editing" : "Разрешить редактирование", @@ -178,8 +177,10 @@ OC.L10N.register( "Expiration" : "Срок действия", "Expiration date" : "Дата окончания", "Note to recipient" : "Примечание для получателя", + "Unshare" : "Закрыть доступ", "Share link" : "Общий доступ по ссылке", - "Enable" : "Использовать", + "Password protect by Talk" : "Защита пароля Talk", + "Could not unshare" : "Невозможно закрыть общий доступ", "Shared with you and the group {group} by {owner}" : "{owner} предоставил(а) доступ Вам и группе {group}", "Shared with you and {circle} by {owner}" : "{owner} предоставил(а) доступ Вам и участникам круга «{circle}»", "Shared with you and the conversation {conversation} by {owner}" : "{owner} предоставил(а) доступ Вам и участникам беседы «{conversation} »", @@ -192,16 +193,13 @@ OC.L10N.register( "email" : "эл. почта", "conversation" : "беседа", "shared by {sharer}" : "{sharer} предоставил(а) доступ", - "Unshare" : "Закрыть доступ", "Can reshare" : "Можно делиться", "Can edit" : "Можно редактировать", "Can create" : "Можно создавать", "Can change" : "Можно изменять", "Can delete" : "Можно удалять", - "Password protect by Talk" : "Защита пароля Talk", "Access control" : "Управление доступом", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} предоставил(а) доступ созданием ссылки", - "Could not unshare" : "Невозможно закрыть общий доступ", "Error while sharing" : "При попытке поделиться произошла ошибка", "Share details could not be loaded for this item." : "Не удалось загрузить информацию об общем доступе для этого элемента.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Для автозавершения требуется как минимум {count} символ.","Для автозавершения требуется как минимум {count} символа.","Для автозавершения требуется как минимум {count} символов.","Для автозавершения требуется как минимум {count} символа."], @@ -210,12 +208,8 @@ OC.L10N.register( "No users found for {search}" : "Не найдено пользователей по запросу {search}", "An error occurred (\"{message}\"). Please try again" : "Произошла ошибка («{message}»). Попробуйте ещё раз", "An error occurred. Please try again" : "Произошла ошибка. Попробуйте ещё раз", - "{sharee} (group)" : "{sharee} (группа)", - "{sharee} (remote)" : "{sharee} (на другом сервере)", "{sharee} (remote group)" : "{sharee} (группа на другом сервере)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (разговор)", "Share" : "Поделиться", "Name or email address..." : "Имя или адрес email…", "Name or federated cloud ID..." : "Имя или ID межсерверного обмена…", @@ -380,6 +374,9 @@ OC.L10N.register( "Error setting expiration date" : "Ошибка при установке срока доступа", "The public link will expire no later than {days} days after it is created" : "Срок действия общедоступной ссылки истекает не позже чем через {days} дней после её создания", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} предоставил(а) доступ созданием ссылки", + "{sharee} (group)" : "{sharee} (группа)", + "{sharee} (remote)" : "{sharee} (на другом сервере)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Поделиться, указав имя пользователя или группы, ID межсерверного обмена хранилища или адрес эл. почты.", "Share with other people by entering a user or group or a federated cloud ID." : "Поделиться, указав имя пользователя или группы или ID межсерверного обмена.", "Share with other people by entering a user or group or an email address." : "Поделиться, указав имя пользователя или группы, либо адрес email.", @@ -411,6 +408,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Вы собираетесь предоставить пользователю %s доступ к вашему аккаунту %s.", "Depending on your configuration, this button could also work to trust the domain:" : "В зависимости от конфигурации, эта кнопка может сделать доверенным следующий домен:", "Copy URL" : "Копировать ссылку", + "Enable" : "Использовать", + "{sharee} (conversation)" : "{sharee} (разговор)", "Please log in before granting %s access to your %s account." : "Пожалуйста, авторизуйтесь до того, как предоставить пользователю %s доступ к вашей учётной записи %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Более подробная информация о том, как это сконфигурировать, может быть найдена в %sдокументации%s." }, diff --git a/core/l10n/ru.json b/core/l10n/ru.json index da774c5ee84..74827aa3dcc 100644 --- a/core/l10n/ru.json +++ b/core/l10n/ru.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Включён режим обслуживания ", "Turned off maintenance mode" : "Отключён режим обслуживания", "Maintenance mode is kept active" : "Режим обслуживания оставлен включенным", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Ожидание завершения работы планировщика (проверка каждые 5 секунд)…", "Updating database schema" : "Выполняется обновление схемы базы данных", "Updated database" : "База данных обновлена", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Проверка возможности обновления схемы базы данных (это может занять длительное время в зависимости от размера базы данных)", @@ -158,12 +157,12 @@ "Choose a password for the public link" : "Укажите пароль для общедоступной ссылки", "Choose a password for the public link or press the \"Enter\" key" : "Укажите пароль для общедоступной ссылки или нажмите «Ввод»", "Copied!" : "Скопировано!", + "Copy link" : "Копировать ссылку", "Not supported!" : "Не поддерживается!", "Press ⌘-C to copy." : "Нажмите ⌘-C для копирования.", "Press Ctrl-C to copy." : "Нажмите Ctrl-C для копирования.", "Resharing is not allowed" : "Повторное открытие доступа запрещено", "Share to {name}" : "Поделиться с {name}", - "Copy link" : "Копировать ссылку", "Link" : "Ссылка", "Password protect" : "Защитить паролем", "Allow editing" : "Разрешить редактирование", @@ -176,8 +175,10 @@ "Expiration" : "Срок действия", "Expiration date" : "Дата окончания", "Note to recipient" : "Примечание для получателя", + "Unshare" : "Закрыть доступ", "Share link" : "Общий доступ по ссылке", - "Enable" : "Использовать", + "Password protect by Talk" : "Защита пароля Talk", + "Could not unshare" : "Невозможно закрыть общий доступ", "Shared with you and the group {group} by {owner}" : "{owner} предоставил(а) доступ Вам и группе {group}", "Shared with you and {circle} by {owner}" : "{owner} предоставил(а) доступ Вам и участникам круга «{circle}»", "Shared with you and the conversation {conversation} by {owner}" : "{owner} предоставил(а) доступ Вам и участникам беседы «{conversation} »", @@ -190,16 +191,13 @@ "email" : "эл. почта", "conversation" : "беседа", "shared by {sharer}" : "{sharer} предоставил(а) доступ", - "Unshare" : "Закрыть доступ", "Can reshare" : "Можно делиться", "Can edit" : "Можно редактировать", "Can create" : "Можно создавать", "Can change" : "Можно изменять", "Can delete" : "Можно удалять", - "Password protect by Talk" : "Защита пароля Talk", "Access control" : "Управление доступом", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} предоставил(а) доступ созданием ссылки", - "Could not unshare" : "Невозможно закрыть общий доступ", "Error while sharing" : "При попытке поделиться произошла ошибка", "Share details could not be loaded for this item." : "Не удалось загрузить информацию об общем доступе для этого элемента.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Для автозавершения требуется как минимум {count} символ.","Для автозавершения требуется как минимум {count} символа.","Для автозавершения требуется как минимум {count} символов.","Для автозавершения требуется как минимум {count} символа."], @@ -208,12 +206,8 @@ "No users found for {search}" : "Не найдено пользователей по запросу {search}", "An error occurred (\"{message}\"). Please try again" : "Произошла ошибка («{message}»). Попробуйте ещё раз", "An error occurred. Please try again" : "Произошла ошибка. Попробуйте ещё раз", - "{sharee} (group)" : "{sharee} (группа)", - "{sharee} (remote)" : "{sharee} (на другом сервере)", "{sharee} (remote group)" : "{sharee} (группа на другом сервере)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (разговор)", "Share" : "Поделиться", "Name or email address..." : "Имя или адрес email…", "Name or federated cloud ID..." : "Имя или ID межсерверного обмена…", @@ -378,6 +372,9 @@ "Error setting expiration date" : "Ошибка при установке срока доступа", "The public link will expire no later than {days} days after it is created" : "Срок действия общедоступной ссылки истекает не позже чем через {days} дней после её создания", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} предоставил(а) доступ созданием ссылки", + "{sharee} (group)" : "{sharee} (группа)", + "{sharee} (remote)" : "{sharee} (на другом сервере)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Поделиться, указав имя пользователя или группы, ID межсерверного обмена хранилища или адрес эл. почты.", "Share with other people by entering a user or group or a federated cloud ID." : "Поделиться, указав имя пользователя или группы или ID межсерверного обмена.", "Share with other people by entering a user or group or an email address." : "Поделиться, указав имя пользователя или группы, либо адрес email.", @@ -409,6 +406,8 @@ "You are about to grant %s access to your %s account." : "Вы собираетесь предоставить пользователю %s доступ к вашему аккаунту %s.", "Depending on your configuration, this button could also work to trust the domain:" : "В зависимости от конфигурации, эта кнопка может сделать доверенным следующий домен:", "Copy URL" : "Копировать ссылку", + "Enable" : "Использовать", + "{sharee} (conversation)" : "{sharee} (разговор)", "Please log in before granting %s access to your %s account." : "Пожалуйста, авторизуйтесь до того, как предоставить пользователю %s доступ к вашей учётной записи %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Более подробная информация о том, как это сконфигурировать, может быть найдена в %sдокументации%s." },"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);" diff --git a/core/l10n/sk.js b/core/l10n/sk.js index 9a66d5e379e..d8d06b3f69a 100644 --- a/core/l10n/sk.js +++ b/core/l10n/sk.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Mód údržby je zapnutý", "Turned off maintenance mode" : "Mód údržby je vypnutý", "Maintenance mode is kept active" : "Režim údržby je stále aktívny", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Čaká sa na dokončenie cronu (skontrolujte znovu za 5 sekúnd) ...", "Updating database schema" : "Aktualizuje sa schéma databázy", "Updated database" : "Databáza je aktualizovaná", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Kontroluje sa, či je možné aktualizovať schému databázy (to môže trvať dlhší čas v závislosti na veľkosti databázy)", @@ -160,12 +159,12 @@ OC.L10N.register( "Choose a password for the public link" : "Zadajte heslo pre tento verejný odkaz", "Choose a password for the public link or press the \"Enter\" key" : "Zvoľte heslo pre verejný link alebo stlačte klávesu \"Enter\"", "Copied!" : "Skopírované!", + "Copy link" : "Kopíruj odkaz", "Not supported!" : "Nie je podporované!", "Press ⌘-C to copy." : "Stlač ⌘-C pre skopírovanie.", "Press Ctrl-C to copy." : "Stlač Ctrl-C pre skopírovanie.", "Resharing is not allowed" : "Sprístupnenie už sprístupnenej položky nie je povolené", "Share to {name}" : "Zdieľať s {name}", - "Copy link" : "Kopíruj odkaz", "Link" : "Odkaz", "Password protect" : "Chrániť heslom", "Allow editing" : "Povoliť úpravy", @@ -178,8 +177,10 @@ OC.L10N.register( "Expiration" : "Koniec platnosti", "Expiration date" : "Dátum expirácie", "Note to recipient" : "Poznámka pre príjemcu", + "Unshare" : "Zneprístupniť", "Share link" : "Sprístupniť odkaz", - "Enable" : "Povoliť", + "Password protect by Talk" : "Chránené heslom apkou Talk", + "Could not unshare" : "Nepodarilo sa zrušiť sprístupnenie", "Shared with you and the group {group} by {owner}" : "Sprístupnené vám a skupine {group} používateľom {owner}", "Shared with you and {circle} by {owner}" : "Sprístupnené vám a {circle} od {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Sprístupnené vám a rozhovoru {conversation} od {owner}", @@ -192,16 +193,13 @@ OC.L10N.register( "email" : "E-mail", "conversation" : "rozhovor", "shared by {sharer}" : "zdieľal {sharer}", - "Unshare" : "Zneprístupniť", "Can reshare" : "Môže opätovne zdieľať", "Can edit" : "Môže upravovať", "Can create" : "Môže vytvárať", "Can change" : "Môže meniť", "Can delete" : "Môže odstraňovať", - "Password protect by Talk" : "Chránené heslom apkou Talk", "Access control" : "Prístupové práva", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} zdieľal pomocou odkazu", - "Could not unshare" : "Nepodarilo sa zrušiť sprístupnenie", "Error while sharing" : "Chyba počas sprístupňovania", "Share details could not be loaded for this item." : "Nebolo možné načítať údaje o sprístupnení tejto položky.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Najmenej {count} znak je potrebný pre autodopĺňanie","Najmenej {count} znaky sú potrebné pre autodopĺňanie","Najmenej {count} znakov je potrebných pre autodopĺňanie","Najmenej {count} znakov je potrebných pre autodopĺňanie"], @@ -210,12 +208,8 @@ OC.L10N.register( "No users found for {search}" : "Výrazu {search} nezodpovedá žiadny používateľ", "An error occurred (\"{message}\"). Please try again" : "Nastala chyba (\"{message}\"). Prosím, skúste znova", "An error occurred. Please try again" : "Nastala chyba. Skúste to prosím znovu", - "{sharee} (group)" : "{sharee} (skupina)", - "{sharee} (remote)" : "{sharee} (vzdialene)", "{sharee} (remote group)" : "{sharee} (vzdialená skupina)", - "{sharee} (email)" : "{sharee} (pošta)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (rozhovor)", "Share" : "Sprístupniť", "Name or email address..." : "Meno alebo e-mailová adresa...", "Name or federated cloud ID..." : "Meno alebo federatívny cloud ID...", @@ -382,6 +376,9 @@ OC.L10N.register( "Error setting expiration date" : "Chyba pri nastavení dátumu expirácie", "The public link will expire no later than {days} days after it is created" : "Verejný odkaz nevyprší skôr než za {days} dní po vytvorení", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} zdieľal pomocou odkazu", + "{sharee} (group)" : "{sharee} (skupina)", + "{sharee} (remote)" : "{sharee} (vzdialene)", + "{sharee} (email)" : "{sharee} (pošta)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Sprístupniť iným ľuďom zadaním používateľa alebo skupiny, federatívneho cloud ID alebo e-mailovej adresy.", "Share with other people by entering a user or group or a federated cloud ID." : "Sprístupniť iným ľuďom zadaním používateľa alebo skupiny, federatívneho cloud ID.", "Share with other people by entering a user or group or an email address." : "Sprístupniť iným ľuďom zadaním používateľa, skupiny alebo e-mailovej adresy.", @@ -413,6 +410,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Chystáte sa udeliť %s prístup k svojmu %s účtu.", "Depending on your configuration, this button could also work to trust the domain:" : "V závislosti od vašej konfigurácie by toto tlačidlo mohlo fungovať tak, že dôverujete doméne:", "Copy URL" : "Kopírovať URL", + "Enable" : "Povoliť", + "{sharee} (conversation)" : "{sharee} (rozhovor)", "Please log in before granting %s access to your %s account." : "Skôr než udelíte prístup pre %s do vášho účtu %s je potrebné sa prihlásiť.", "Further information how to configure this can be found in the %sdocumentation%s." : "Viac informácií o konfigurácii je možné nájsť v %sdokumentácii%s." }, diff --git a/core/l10n/sk.json b/core/l10n/sk.json index d6c86110020..6fd07fced04 100644 --- a/core/l10n/sk.json +++ b/core/l10n/sk.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Mód údržby je zapnutý", "Turned off maintenance mode" : "Mód údržby je vypnutý", "Maintenance mode is kept active" : "Režim údržby je stále aktívny", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Čaká sa na dokončenie cronu (skontrolujte znovu za 5 sekúnd) ...", "Updating database schema" : "Aktualizuje sa schéma databázy", "Updated database" : "Databáza je aktualizovaná", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Kontroluje sa, či je možné aktualizovať schému databázy (to môže trvať dlhší čas v závislosti na veľkosti databázy)", @@ -158,12 +157,12 @@ "Choose a password for the public link" : "Zadajte heslo pre tento verejný odkaz", "Choose a password for the public link or press the \"Enter\" key" : "Zvoľte heslo pre verejný link alebo stlačte klávesu \"Enter\"", "Copied!" : "Skopírované!", + "Copy link" : "Kopíruj odkaz", "Not supported!" : "Nie je podporované!", "Press ⌘-C to copy." : "Stlač ⌘-C pre skopírovanie.", "Press Ctrl-C to copy." : "Stlač Ctrl-C pre skopírovanie.", "Resharing is not allowed" : "Sprístupnenie už sprístupnenej položky nie je povolené", "Share to {name}" : "Zdieľať s {name}", - "Copy link" : "Kopíruj odkaz", "Link" : "Odkaz", "Password protect" : "Chrániť heslom", "Allow editing" : "Povoliť úpravy", @@ -176,8 +175,10 @@ "Expiration" : "Koniec platnosti", "Expiration date" : "Dátum expirácie", "Note to recipient" : "Poznámka pre príjemcu", + "Unshare" : "Zneprístupniť", "Share link" : "Sprístupniť odkaz", - "Enable" : "Povoliť", + "Password protect by Talk" : "Chránené heslom apkou Talk", + "Could not unshare" : "Nepodarilo sa zrušiť sprístupnenie", "Shared with you and the group {group} by {owner}" : "Sprístupnené vám a skupine {group} používateľom {owner}", "Shared with you and {circle} by {owner}" : "Sprístupnené vám a {circle} od {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Sprístupnené vám a rozhovoru {conversation} od {owner}", @@ -190,16 +191,13 @@ "email" : "E-mail", "conversation" : "rozhovor", "shared by {sharer}" : "zdieľal {sharer}", - "Unshare" : "Zneprístupniť", "Can reshare" : "Môže opätovne zdieľať", "Can edit" : "Môže upravovať", "Can create" : "Môže vytvárať", "Can change" : "Môže meniť", "Can delete" : "Môže odstraňovať", - "Password protect by Talk" : "Chránené heslom apkou Talk", "Access control" : "Prístupové práva", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} zdieľal pomocou odkazu", - "Could not unshare" : "Nepodarilo sa zrušiť sprístupnenie", "Error while sharing" : "Chyba počas sprístupňovania", "Share details could not be loaded for this item." : "Nebolo možné načítať údaje o sprístupnení tejto položky.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Najmenej {count} znak je potrebný pre autodopĺňanie","Najmenej {count} znaky sú potrebné pre autodopĺňanie","Najmenej {count} znakov je potrebných pre autodopĺňanie","Najmenej {count} znakov je potrebných pre autodopĺňanie"], @@ -208,12 +206,8 @@ "No users found for {search}" : "Výrazu {search} nezodpovedá žiadny používateľ", "An error occurred (\"{message}\"). Please try again" : "Nastala chyba (\"{message}\"). Prosím, skúste znova", "An error occurred. Please try again" : "Nastala chyba. Skúste to prosím znovu", - "{sharee} (group)" : "{sharee} (skupina)", - "{sharee} (remote)" : "{sharee} (vzdialene)", "{sharee} (remote group)" : "{sharee} (vzdialená skupina)", - "{sharee} (email)" : "{sharee} (pošta)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (rozhovor)", "Share" : "Sprístupniť", "Name or email address..." : "Meno alebo e-mailová adresa...", "Name or federated cloud ID..." : "Meno alebo federatívny cloud ID...", @@ -380,6 +374,9 @@ "Error setting expiration date" : "Chyba pri nastavení dátumu expirácie", "The public link will expire no later than {days} days after it is created" : "Verejný odkaz nevyprší skôr než za {days} dní po vytvorení", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} zdieľal pomocou odkazu", + "{sharee} (group)" : "{sharee} (skupina)", + "{sharee} (remote)" : "{sharee} (vzdialene)", + "{sharee} (email)" : "{sharee} (pošta)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Sprístupniť iným ľuďom zadaním používateľa alebo skupiny, federatívneho cloud ID alebo e-mailovej adresy.", "Share with other people by entering a user or group or a federated cloud ID." : "Sprístupniť iným ľuďom zadaním používateľa alebo skupiny, federatívneho cloud ID.", "Share with other people by entering a user or group or an email address." : "Sprístupniť iným ľuďom zadaním používateľa, skupiny alebo e-mailovej adresy.", @@ -411,6 +408,8 @@ "You are about to grant %s access to your %s account." : "Chystáte sa udeliť %s prístup k svojmu %s účtu.", "Depending on your configuration, this button could also work to trust the domain:" : "V závislosti od vašej konfigurácie by toto tlačidlo mohlo fungovať tak, že dôverujete doméne:", "Copy URL" : "Kopírovať URL", + "Enable" : "Povoliť", + "{sharee} (conversation)" : "{sharee} (rozhovor)", "Please log in before granting %s access to your %s account." : "Skôr než udelíte prístup pre %s do vášho účtu %s je potrebné sa prihlásiť.", "Further information how to configure this can be found in the %sdocumentation%s." : "Viac informácií o konfigurácii je možné nájsť v %sdokumentácii%s." },"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);" diff --git a/core/l10n/sl.js b/core/l10n/sl.js index 1a6bf3a645e..a58ad98c8ea 100644 --- a/core/l10n/sl.js +++ b/core/l10n/sl.js @@ -111,12 +111,12 @@ OC.L10N.register( "Choose a password for the public link" : "Izberite geslo za javno povezavo", "Choose a password for the public link or press the \"Enter\" key" : "Izberite geslo za javno povezavo ali pritisnite \"Enter\"", "Copied!" : "Naslov je kopiran!", + "Copy link" : "Kopiraj povezavo", "Not supported!" : "Ni podprto!", "Press ⌘-C to copy." : "Pritisni ⌘-C za kopiranje.", "Press Ctrl-C to copy." : "Pritisni Ctrl-C za kopiranje.", "Resharing is not allowed" : "Nadaljnja souporaba ni dovoljena", "Share to {name}" : "Deli z {name}", - "Copy link" : "Kopiraj povezavo", "Link" : "Povezava", "Password protect" : "Zaščiti z geslom", "Allow editing" : "Dovoli urejanje", @@ -129,8 +129,9 @@ OC.L10N.register( "Expiration" : "Datum preteka", "Expiration date" : "Datum preteka", "Note to recipient" : "Pošlji opombo prejemniku", + "Unshare" : "Prekliči souporabo", "Share link" : "Povezava za prejem", - "Enable" : "Omogoči", + "Could not unshare" : "Ni mogoče preklicati souporabe", "Shared with you and the group {group} by {owner}" : "V souporabi z vami in skupino {group}. Lastnik je {owner}.", "Shared with you by {owner}" : "V souporabi z vami. Lastnik je {owner}.", "group" : "skupina", @@ -139,22 +140,17 @@ OC.L10N.register( "email" : "e-pošta", "conversation" : "pogovor", "shared by {sharer}" : "deli {sharer}", - "Unshare" : "Prekliči souporabo", "Can reshare" : "Lahko deli naprej", "Can edit" : "Lahko ureja", "Can create" : "Lahko ustvari", "Can change" : "Lahko spremeni", "Can delete" : "Lahko izbriše", "Access control" : "Nadzor dostopa", - "Could not unshare" : "Ni mogoče preklicati souporabe", "Error while sharing" : "Napaka med omogočanjem souporabe", "Share details could not be loaded for this item." : "Podrobnosti souporabe za te predmet ni mogoče naložiti.", "No users or groups found for {search}" : "Ni najdenih uporabnikov ali skupin za {search}", "No users found for {search}" : "Ni uporabnikov, skladnih z iskalnim nizom {search}", "An error occurred. Please try again" : "Prišlo je do napake. Poskusite znova.", - "{sharee} (group)" : "{sharee} (skupina)", - "{sharee} (remote)" : "{sharee} (oddaljeno)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Souporaba", "Name or email address..." : "Ime ali e-poštni naslov...", @@ -265,6 +261,9 @@ OC.L10N.register( "Updated \"%s\" to %s" : "Datoteka \"%s\" je posodobljena na %s", "Error setting expiration date" : "Napaka nastavljanja datuma preteka", "The public link will expire no later than {days} days after it is created" : "Javna povezava bo potekla {days} dni po ustvarjanju.", + "{sharee} (group)" : "{sharee} (skupina)", + "{sharee} (remote)" : "{sharee} (oddaljeno)", + "{sharee} (email)" : "{sharee} (email)", "The specified document has not been found on the server." : "Določenega dokumenta na strežniku ni mogoče najti.", "You can click here to return to %s." : "S klikom na povezavo boste vrnjeni na %s.", "Wrong password. Reset it?" : "Napačno geslo. Ali ga želite ponastaviti?", @@ -276,6 +275,7 @@ OC.L10N.register( "This page will refresh itself when the %s instance is available again." : "Stran bo osvežena ko bo %s spet na voljo.", "Thank you for your patience." : "Hvala za potrpežljivost!", "Back to log in" : "Nazaj na prijavo", - "Copy URL" : "Kopiraj naslov URL" + "Copy URL" : "Kopiraj naslov URL", + "Enable" : "Omogoči" }, "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"); diff --git a/core/l10n/sl.json b/core/l10n/sl.json index 15ffbd56712..f91f141b1bb 100644 --- a/core/l10n/sl.json +++ b/core/l10n/sl.json @@ -109,12 +109,12 @@ "Choose a password for the public link" : "Izberite geslo za javno povezavo", "Choose a password for the public link or press the \"Enter\" key" : "Izberite geslo za javno povezavo ali pritisnite \"Enter\"", "Copied!" : "Naslov je kopiran!", + "Copy link" : "Kopiraj povezavo", "Not supported!" : "Ni podprto!", "Press ⌘-C to copy." : "Pritisni ⌘-C za kopiranje.", "Press Ctrl-C to copy." : "Pritisni Ctrl-C za kopiranje.", "Resharing is not allowed" : "Nadaljnja souporaba ni dovoljena", "Share to {name}" : "Deli z {name}", - "Copy link" : "Kopiraj povezavo", "Link" : "Povezava", "Password protect" : "Zaščiti z geslom", "Allow editing" : "Dovoli urejanje", @@ -127,8 +127,9 @@ "Expiration" : "Datum preteka", "Expiration date" : "Datum preteka", "Note to recipient" : "Pošlji opombo prejemniku", + "Unshare" : "Prekliči souporabo", "Share link" : "Povezava za prejem", - "Enable" : "Omogoči", + "Could not unshare" : "Ni mogoče preklicati souporabe", "Shared with you and the group {group} by {owner}" : "V souporabi z vami in skupino {group}. Lastnik je {owner}.", "Shared with you by {owner}" : "V souporabi z vami. Lastnik je {owner}.", "group" : "skupina", @@ -137,22 +138,17 @@ "email" : "e-pošta", "conversation" : "pogovor", "shared by {sharer}" : "deli {sharer}", - "Unshare" : "Prekliči souporabo", "Can reshare" : "Lahko deli naprej", "Can edit" : "Lahko ureja", "Can create" : "Lahko ustvari", "Can change" : "Lahko spremeni", "Can delete" : "Lahko izbriše", "Access control" : "Nadzor dostopa", - "Could not unshare" : "Ni mogoče preklicati souporabe", "Error while sharing" : "Napaka med omogočanjem souporabe", "Share details could not be loaded for this item." : "Podrobnosti souporabe za te predmet ni mogoče naložiti.", "No users or groups found for {search}" : "Ni najdenih uporabnikov ali skupin za {search}", "No users found for {search}" : "Ni uporabnikov, skladnih z iskalnim nizom {search}", "An error occurred. Please try again" : "Prišlo je do napake. Poskusite znova.", - "{sharee} (group)" : "{sharee} (skupina)", - "{sharee} (remote)" : "{sharee} (oddaljeno)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Souporaba", "Name or email address..." : "Ime ali e-poštni naslov...", @@ -263,6 +259,9 @@ "Updated \"%s\" to %s" : "Datoteka \"%s\" je posodobljena na %s", "Error setting expiration date" : "Napaka nastavljanja datuma preteka", "The public link will expire no later than {days} days after it is created" : "Javna povezava bo potekla {days} dni po ustvarjanju.", + "{sharee} (group)" : "{sharee} (skupina)", + "{sharee} (remote)" : "{sharee} (oddaljeno)", + "{sharee} (email)" : "{sharee} (email)", "The specified document has not been found on the server." : "Določenega dokumenta na strežniku ni mogoče najti.", "You can click here to return to %s." : "S klikom na povezavo boste vrnjeni na %s.", "Wrong password. Reset it?" : "Napačno geslo. Ali ga želite ponastaviti?", @@ -274,6 +273,7 @@ "This page will refresh itself when the %s instance is available again." : "Stran bo osvežena ko bo %s spet na voljo.", "Thank you for your patience." : "Hvala za potrpežljivost!", "Back to log in" : "Nazaj na prijavo", - "Copy URL" : "Kopiraj naslov URL" + "Copy URL" : "Kopiraj naslov URL", + "Enable" : "Omogoči" },"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" }
\ No newline at end of file diff --git a/core/l10n/sq.js b/core/l10n/sq.js index f67d4ff4646..fc7bcb05ba5 100644 --- a/core/l10n/sq.js +++ b/core/l10n/sq.js @@ -128,8 +128,9 @@ OC.L10N.register( "Set expiration date" : "Caktoni datë skadimi", "Expiration" : "Skadim", "Expiration date" : "Datë skadimi", + "Unshare" : "Hiqe ndarjen", "Share link" : "Lidhje ndarjeje", - "Enable" : "Aktivizo", + "Could not unshare" : "S’e shndau dot", "Shared with you and the group {group} by {owner}" : "Ndarë me ju dhe me grupin {group} nga {owner}", "Shared with you by {owner}" : "Ndarë me ju nga {owner}", "Choose a password for the mail share" : "Zgjidh një fjalëkalim për shpërndarjen e mail-it", @@ -138,14 +139,12 @@ OC.L10N.register( "email" : "postë elektronike", "conversation" : "bisedë", "shared by {sharer}" : "ndarë nga {ndarësi}", - "Unshare" : "Hiqe ndarjen", "Can reshare" : "Mund të rishpërdajë", "Can edit" : "Mund të editojë", "Can create" : "Mund të krijoni", "Can change" : "Mund të ndryshojë", "Can delete" : "Mund të fshijë", "Access control" : "Kontrolli i aksesit", - "Could not unshare" : "S’e shndau dot", "Error while sharing" : "Gabim gjatë ndarjes", "Share details could not be loaded for this item." : "Për këtë objekt s’u ngarkuan dot hollësi ndarjeje.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Të paktën {count} karaktere janë të nevojshëm për vetëpërmbushje","Të paktën {count} karaktere janë të nevojshëm për vetëpërmbushje"], @@ -153,9 +152,6 @@ OC.L10N.register( "No users or groups found for {search}" : "S’u gjetën përdorues ose grupe për {search}", "No users found for {search}" : "S’u gjet përdorues për {search}", "An error occurred. Please try again" : "Ndodhi një gabim. Ju lutemi, riprovoni", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (i largët)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Ndaje", "Name or email address..." : "Emri ose adresa e email-it", @@ -277,6 +273,9 @@ OC.L10N.register( "Error setting expiration date" : "Gabim në caktimin e datës së skadimit", "The public link will expire no later than {days} days after it is created" : "Lidhja publike do të skadojë jo më vonë se {days} ditë pas krijimit të saj", "{{shareInitiatorDisplayName}} shared via link" : "{{shpërndaEmrinEShfaqurTëNismëtarit}} shpërnda nëpërmjet linkut", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (i largët)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Shpërndaje me persona të tjerë duke vendosur një përdorues ose një grup, një ID reje të federuar ose një adresë emaili", "Share with other people by entering a user or group or a federated cloud ID." : "Ndaj me njerëz të tjerë duke futur një pëdorues ose grup ose një ID reje federale.", "Share with other people by entering a user or group or an email address." : "Shpërndaje me persona të tjerë duke vendosur një perdorues ose një grup ose një adresë emaili", @@ -291,6 +290,7 @@ OC.L10N.register( "%s will be updated to version %s" : "%s do të përditësohet me versionin %s", "For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Për ndihmë, shihni <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentimin</a>.", "This page will refresh itself when the %s instance is available again." : "Kjo faqe do të rifreskohet vetiu, sapo instanca %s të jetë sërish gati.", - "Thank you for your patience." : "Ju faleminderit për durimin." + "Thank you for your patience." : "Ju faleminderit për durimin.", + "Enable" : "Aktivizo" }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/sq.json b/core/l10n/sq.json index 216537139b5..8b45f707f14 100644 --- a/core/l10n/sq.json +++ b/core/l10n/sq.json @@ -126,8 +126,9 @@ "Set expiration date" : "Caktoni datë skadimi", "Expiration" : "Skadim", "Expiration date" : "Datë skadimi", + "Unshare" : "Hiqe ndarjen", "Share link" : "Lidhje ndarjeje", - "Enable" : "Aktivizo", + "Could not unshare" : "S’e shndau dot", "Shared with you and the group {group} by {owner}" : "Ndarë me ju dhe me grupin {group} nga {owner}", "Shared with you by {owner}" : "Ndarë me ju nga {owner}", "Choose a password for the mail share" : "Zgjidh një fjalëkalim për shpërndarjen e mail-it", @@ -136,14 +137,12 @@ "email" : "postë elektronike", "conversation" : "bisedë", "shared by {sharer}" : "ndarë nga {ndarësi}", - "Unshare" : "Hiqe ndarjen", "Can reshare" : "Mund të rishpërdajë", "Can edit" : "Mund të editojë", "Can create" : "Mund të krijoni", "Can change" : "Mund të ndryshojë", "Can delete" : "Mund të fshijë", "Access control" : "Kontrolli i aksesit", - "Could not unshare" : "S’e shndau dot", "Error while sharing" : "Gabim gjatë ndarjes", "Share details could not be loaded for this item." : "Për këtë objekt s’u ngarkuan dot hollësi ndarjeje.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Të paktën {count} karaktere janë të nevojshëm për vetëpërmbushje","Të paktën {count} karaktere janë të nevojshëm për vetëpërmbushje"], @@ -151,9 +150,6 @@ "No users or groups found for {search}" : "S’u gjetën përdorues ose grupe për {search}", "No users found for {search}" : "S’u gjet përdorues për {search}", "An error occurred. Please try again" : "Ndodhi një gabim. Ju lutemi, riprovoni", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (i largët)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Ndaje", "Name or email address..." : "Emri ose adresa e email-it", @@ -275,6 +271,9 @@ "Error setting expiration date" : "Gabim në caktimin e datës së skadimit", "The public link will expire no later than {days} days after it is created" : "Lidhja publike do të skadojë jo më vonë se {days} ditë pas krijimit të saj", "{{shareInitiatorDisplayName}} shared via link" : "{{shpërndaEmrinEShfaqurTëNismëtarit}} shpërnda nëpërmjet linkut", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (i largët)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Shpërndaje me persona të tjerë duke vendosur një përdorues ose një grup, një ID reje të federuar ose një adresë emaili", "Share with other people by entering a user or group or a federated cloud ID." : "Ndaj me njerëz të tjerë duke futur një pëdorues ose grup ose një ID reje federale.", "Share with other people by entering a user or group or an email address." : "Shpërndaje me persona të tjerë duke vendosur një perdorues ose një grup ose një adresë emaili", @@ -289,6 +288,7 @@ "%s will be updated to version %s" : "%s do të përditësohet me versionin %s", "For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Për ndihmë, shihni <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentimin</a>.", "This page will refresh itself when the %s instance is available again." : "Kjo faqe do të rifreskohet vetiu, sapo instanca %s të jetë sërish gati.", - "Thank you for your patience." : "Ju faleminderit për durimin." + "Thank you for your patience." : "Ju faleminderit për durimin.", + "Enable" : "Aktivizo" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/core/l10n/sr.js b/core/l10n/sr.js index 1d371ee480b..bc464191177 100644 --- a/core/l10n/sr.js +++ b/core/l10n/sr.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Режим одржавања укључен", "Turned off maintenance mode" : "Режим одржавања искључен", "Maintenance mode is kept active" : "Режим одржавања се држи активним", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Чекање да се заврши крон (проверите опет за 5 секунди) …", "Updating database schema" : "Освежава се шема базе података", "Updated database" : "База података ажурирана", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Провера да ли шема базе података може да се ажурира (ово може потрајати, у зависности колика је база)", @@ -160,12 +159,12 @@ OC.L10N.register( "Choose a password for the public link" : "Унесите лозинку за јавну везу", "Choose a password for the public link or press the \"Enter\" key" : "Унесите лозинку за јавну везу или притисните \"Ентер\"", "Copied!" : "Копирано!", + "Copy link" : "Копирај везу", "Not supported!" : "Није подржано!", "Press ⌘-C to copy." : "Притисни ⌘-C за копирање.", "Press Ctrl-C to copy." : "Притисни Ctrl-C за копирање.", "Resharing is not allowed" : "Поновно дељење није дозвољено", "Share to {name}" : "Подели са {name}", - "Copy link" : "Копирај везу", "Link" : "Веза", "Password protect" : "Заштићено лозинком", "Allow editing" : "Дозволи уређивање", @@ -178,8 +177,10 @@ OC.L10N.register( "Expiration" : "Истиче", "Expiration date" : "Датум истека", "Note to recipient" : "Белешка примаоцу", + "Unshare" : "Укини дељење", "Share link" : "Веза дељења", - "Enable" : "Укључи", + "Password protect by Talk" : "Заштити лозинком преко Talk-а", + "Could not unshare" : "Не могу да укинем дељење", "Shared with you and the group {group} by {owner}" : "{owner} дели са вама и са групом {group}.", "Shared with you and {circle} by {owner}" : "Дељемп са Вама и кругом {circle} од стране корисника {owner}", "Shared with you and the conversation {conversation} by {owner}" : "{owner} поделио са Вама и у разговору {conversation}", @@ -192,16 +193,13 @@ OC.L10N.register( "email" : "е-пошта", "conversation" : "разговор", "shared by {sharer}" : "поделио је {sharer}", - "Unshare" : "Укини дељење", "Can reshare" : "Може да дели даље", "Can edit" : "Може да мења", "Can create" : "Може да направи", "Can change" : "Може да мења", "Can delete" : "Може да брише", - "Password protect by Talk" : "Заштити лозинком преко Talk-а", "Access control" : "Контрола приступа", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} је поделио преко везе", - "Could not unshare" : "Не могу да укинем дељење", "Error while sharing" : "Грешка при дељењу", "Share details could not be loaded for this item." : "Не могу да учитам детаље дељења за ову ставку.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Најмање {count} слово је потребно за аутокомплетирање","Најмање {count} слова је потребно за аутокомплетирање","Најмање {count} слова је потребно за аутокомплетирање"], @@ -210,12 +208,8 @@ OC.L10N.register( "No users found for {search}" : "Није нађен ниједан корисник за претрагу {search}", "An error occurred (\"{message}\"). Please try again" : "Десила се грешка (\"{message}\"). Покушајте поново.", "An error occurred. Please try again" : "Дошло је до грешке. Покушајте поново", - "{sharee} (group)" : "{sharee} (група)", - "{sharee} (remote)" : "{sharee} (удаљено)", "{sharee} (remote group)" : "{sharee} (удаљена група)", - "{sharee} (email)" : "{sharee} (е-пошта)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (разговор)", "Share" : "Дели", "Name or email address..." : "Име или адреса е-поште...", "Name or federated cloud ID..." : "Име или ID здруженог облака...", @@ -382,6 +376,9 @@ OC.L10N.register( "Error setting expiration date" : "Грешка при постављању датума истека", "The public link will expire no later than {days} days after it is created" : "Јавна веза ће престати да важи {days} дана након стварања", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} је поделио преко везе", + "{sharee} (group)" : "{sharee} (група)", + "{sharee} (remote)" : "{sharee} (удаљено)", + "{sharee} (email)" : "{sharee} (е-пошта)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Делите са другим људима тако што унесете корисника, групу, ID здруженог облака или адресу е-поште. ", "Share with other people by entering a user or group or a federated cloud ID." : "Делите са другим људима тако што унесете корисника, групу или ID здруженог облака.", "Share with other people by entering a user or group or an email address." : "Делите са другим људима тако што унесете корисника или групу.", @@ -413,6 +410,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Управо ћете одобрити %s приступ Вашем %s налогу.", "Depending on your configuration, this button could also work to trust the domain:" : "У зависности од Ваше конфигурације, овим дугметом може да послужи да почнете да верујете овом домену:", "Copy URL" : "Копирај URL", + "Enable" : "Укључи", + "{sharee} (conversation)" : "{sharee} (разговор)", "Please log in before granting %s access to your %s account." : "Прво се пријавите пре него што одобрите привилегију %s приступ Вашем налогу %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Више информација о томе како ово подесити можете да нађете у %s документацији%s." }, diff --git a/core/l10n/sr.json b/core/l10n/sr.json index f6a3c9a2ed4..5368c202231 100644 --- a/core/l10n/sr.json +++ b/core/l10n/sr.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Режим одржавања укључен", "Turned off maintenance mode" : "Режим одржавања искључен", "Maintenance mode is kept active" : "Режим одржавања се држи активним", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Чекање да се заврши крон (проверите опет за 5 секунди) …", "Updating database schema" : "Освежава се шема базе података", "Updated database" : "База података ажурирана", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Провера да ли шема базе података може да се ажурира (ово може потрајати, у зависности колика је база)", @@ -158,12 +157,12 @@ "Choose a password for the public link" : "Унесите лозинку за јавну везу", "Choose a password for the public link or press the \"Enter\" key" : "Унесите лозинку за јавну везу или притисните \"Ентер\"", "Copied!" : "Копирано!", + "Copy link" : "Копирај везу", "Not supported!" : "Није подржано!", "Press ⌘-C to copy." : "Притисни ⌘-C за копирање.", "Press Ctrl-C to copy." : "Притисни Ctrl-C за копирање.", "Resharing is not allowed" : "Поновно дељење није дозвољено", "Share to {name}" : "Подели са {name}", - "Copy link" : "Копирај везу", "Link" : "Веза", "Password protect" : "Заштићено лозинком", "Allow editing" : "Дозволи уређивање", @@ -176,8 +175,10 @@ "Expiration" : "Истиче", "Expiration date" : "Датум истека", "Note to recipient" : "Белешка примаоцу", + "Unshare" : "Укини дељење", "Share link" : "Веза дељења", - "Enable" : "Укључи", + "Password protect by Talk" : "Заштити лозинком преко Talk-а", + "Could not unshare" : "Не могу да укинем дељење", "Shared with you and the group {group} by {owner}" : "{owner} дели са вама и са групом {group}.", "Shared with you and {circle} by {owner}" : "Дељемп са Вама и кругом {circle} од стране корисника {owner}", "Shared with you and the conversation {conversation} by {owner}" : "{owner} поделио са Вама и у разговору {conversation}", @@ -190,16 +191,13 @@ "email" : "е-пошта", "conversation" : "разговор", "shared by {sharer}" : "поделио је {sharer}", - "Unshare" : "Укини дељење", "Can reshare" : "Може да дели даље", "Can edit" : "Може да мења", "Can create" : "Може да направи", "Can change" : "Може да мења", "Can delete" : "Може да брише", - "Password protect by Talk" : "Заштити лозинком преко Talk-а", "Access control" : "Контрола приступа", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} је поделио преко везе", - "Could not unshare" : "Не могу да укинем дељење", "Error while sharing" : "Грешка при дељењу", "Share details could not be loaded for this item." : "Не могу да учитам детаље дељења за ову ставку.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Најмање {count} слово је потребно за аутокомплетирање","Најмање {count} слова је потребно за аутокомплетирање","Најмање {count} слова је потребно за аутокомплетирање"], @@ -208,12 +206,8 @@ "No users found for {search}" : "Није нађен ниједан корисник за претрагу {search}", "An error occurred (\"{message}\"). Please try again" : "Десила се грешка (\"{message}\"). Покушајте поново.", "An error occurred. Please try again" : "Дошло је до грешке. Покушајте поново", - "{sharee} (group)" : "{sharee} (група)", - "{sharee} (remote)" : "{sharee} (удаљено)", "{sharee} (remote group)" : "{sharee} (удаљена група)", - "{sharee} (email)" : "{sharee} (е-пошта)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (разговор)", "Share" : "Дели", "Name or email address..." : "Име или адреса е-поште...", "Name or federated cloud ID..." : "Име или ID здруженог облака...", @@ -380,6 +374,9 @@ "Error setting expiration date" : "Грешка при постављању датума истека", "The public link will expire no later than {days} days after it is created" : "Јавна веза ће престати да важи {days} дана након стварања", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} је поделио преко везе", + "{sharee} (group)" : "{sharee} (група)", + "{sharee} (remote)" : "{sharee} (удаљено)", + "{sharee} (email)" : "{sharee} (е-пошта)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Делите са другим људима тако што унесете корисника, групу, ID здруженог облака или адресу е-поште. ", "Share with other people by entering a user or group or a federated cloud ID." : "Делите са другим људима тако што унесете корисника, групу или ID здруженог облака.", "Share with other people by entering a user or group or an email address." : "Делите са другим људима тако што унесете корисника или групу.", @@ -411,6 +408,8 @@ "You are about to grant %s access to your %s account." : "Управо ћете одобрити %s приступ Вашем %s налогу.", "Depending on your configuration, this button could also work to trust the domain:" : "У зависности од Ваше конфигурације, овим дугметом може да послужи да почнете да верујете овом домену:", "Copy URL" : "Копирај URL", + "Enable" : "Укључи", + "{sharee} (conversation)" : "{sharee} (разговор)", "Please log in before granting %s access to your %s account." : "Прво се пријавите пре него што одобрите привилегију %s приступ Вашем налогу %s.", "Further information how to configure this can be found in the %sdocumentation%s." : "Више информација о томе како ово подесити можете да нађете у %s документацији%s." },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" diff --git a/core/l10n/sv.js b/core/l10n/sv.js index f48fc60e087..215c6101427 100644 --- a/core/l10n/sv.js +++ b/core/l10n/sv.js @@ -120,12 +120,12 @@ OC.L10N.register( "Choose a password for the public link" : "Välj ett lösenord för den offentliga länken", "Choose a password for the public link or press the \"Enter\" key" : "Välj ett lösenord för den publika länken eller tryck Enter", "Copied!" : "Kopierad!", + "Copy link" : "Kopiera länk", "Not supported!" : "Stöds ej!", "Press ⌘-C to copy." : "Tryck ned ⌘-C för att kopiera.", "Press Ctrl-C to copy." : "Tryck ned Ctrl-C för att kopiera.", "Resharing is not allowed" : "Dela vidare är inte tillåtet", "Share to {name}" : "Dela till {name}", - "Copy link" : "Kopiera länk", "Link" : "Länk", "Password protect" : "Lösenordsskydda", "Allow editing" : "Tillåt redigering", @@ -138,8 +138,10 @@ OC.L10N.register( "Expiration" : "Upphör", "Expiration date" : "Utgångsdatum", "Note to recipient" : "Notering till mottagare", + "Unshare" : "Sluta dela", "Share link" : "Dela länk", - "Enable" : "Aktivera", + "Password protect by Talk" : "Lösenordsskydda med Talk", + "Could not unshare" : "Kunde inte ta bort delning", "Shared with you and the group {group} by {owner}" : "Delad med dig och gruppen {group} av {owner}", "Shared with you and {circle} by {owner}" : "Delad med dig och {circle} av {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Delad med dig och konversation {conversation} av {owner}", @@ -152,16 +154,13 @@ OC.L10N.register( "email" : "e-post", "conversation" : "Konversation", "shared by {sharer}" : "delat av {sharer}", - "Unshare" : "Sluta dela", "Can reshare" : "Kan dela vidare", "Can edit" : "Kan redigera", "Can create" : "Kan skapa", "Can change" : "Kan ändra", "Can delete" : "Kan radera", - "Password protect by Talk" : "Lösenordsskydda med Talk", "Access control" : "Åtkomstkontroll", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} delad via länk", - "Could not unshare" : "Kunde inte ta bort delning", "Error while sharing" : "Fel vid delning", "Share details could not be loaded for this item." : "Delningsdetaljer kunde inte laddas för detta objekt.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Minst {count} tecken krävs för automatisk ifyllning","Minst {count} tecken krävs för automatisk ifyllning"], @@ -170,9 +169,6 @@ OC.L10N.register( "No users found for {search}" : "Inga användare funna för {search}", "An error occurred (\"{message}\"). Please try again" : "Ett fel uppstod (\"{message}\"). Försök igen", "An error occurred. Please try again" : "Ett fel uppstod. Vänligen försök igen", - "{sharee} (group)" : "{sharee} (grupp)", - "{sharee} (remote)" : "{sharee} (externt)", - "{sharee} (email)" : "{sharee} (e-post)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Dela", "Name or email address..." : "Namn eller e-postadress", @@ -322,6 +318,9 @@ OC.L10N.register( "Error setting expiration date" : "Fel vid val av utgångsdatum", "The public link will expire no later than {days} days after it is created" : "Den offentliga länken kommer sluta gälla inte senare än {days} dagar efter att den skapades", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delad via länk", + "{sharee} (group)" : "{sharee} (grupp)", + "{sharee} (remote)" : "{sharee} (externt)", + "{sharee} (email)" : "{sharee} (e-post)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Dela med andra personer genom att ange användarnamn, grupp, ett federerat moln-ID eller en e-postadress.", "Share with other people by entering a user or group or a federated cloud ID." : "Dela med andra personer genom att ange användarnamn, grupp eller ett federerat moln-ID.", "Share with other people by entering a user or group or an email address." : "Dela med andra personer genom att ange användarnamn, grupp eller en e-postadress.", @@ -346,6 +345,7 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "Du håller på att ge %s tillgång till ditt %s-konto.", "Depending on your configuration, this button could also work to trust the domain:" : "Beroende på din konfiguration kan denna knappen också fungera föra att lita på domänen:", "Copy URL" : "Kopiera URL", + "Enable" : "Aktivera", "Please log in before granting %s access to your %s account." : "Logga in innan du ger %s åtkomst till ditt %s konto.", "Further information how to configure this can be found in the %sdocumentation%s." : "Ytterligare information hur du konfigurerar detta finns i %sdokumentationen%s." }, diff --git a/core/l10n/sv.json b/core/l10n/sv.json index 2d20e804a8d..abeac628423 100644 --- a/core/l10n/sv.json +++ b/core/l10n/sv.json @@ -118,12 +118,12 @@ "Choose a password for the public link" : "Välj ett lösenord för den offentliga länken", "Choose a password for the public link or press the \"Enter\" key" : "Välj ett lösenord för den publika länken eller tryck Enter", "Copied!" : "Kopierad!", + "Copy link" : "Kopiera länk", "Not supported!" : "Stöds ej!", "Press ⌘-C to copy." : "Tryck ned ⌘-C för att kopiera.", "Press Ctrl-C to copy." : "Tryck ned Ctrl-C för att kopiera.", "Resharing is not allowed" : "Dela vidare är inte tillåtet", "Share to {name}" : "Dela till {name}", - "Copy link" : "Kopiera länk", "Link" : "Länk", "Password protect" : "Lösenordsskydda", "Allow editing" : "Tillåt redigering", @@ -136,8 +136,10 @@ "Expiration" : "Upphör", "Expiration date" : "Utgångsdatum", "Note to recipient" : "Notering till mottagare", + "Unshare" : "Sluta dela", "Share link" : "Dela länk", - "Enable" : "Aktivera", + "Password protect by Talk" : "Lösenordsskydda med Talk", + "Could not unshare" : "Kunde inte ta bort delning", "Shared with you and the group {group} by {owner}" : "Delad med dig och gruppen {group} av {owner}", "Shared with you and {circle} by {owner}" : "Delad med dig och {circle} av {owner}", "Shared with you and the conversation {conversation} by {owner}" : "Delad med dig och konversation {conversation} av {owner}", @@ -150,16 +152,13 @@ "email" : "e-post", "conversation" : "Konversation", "shared by {sharer}" : "delat av {sharer}", - "Unshare" : "Sluta dela", "Can reshare" : "Kan dela vidare", "Can edit" : "Kan redigera", "Can create" : "Kan skapa", "Can change" : "Kan ändra", "Can delete" : "Kan radera", - "Password protect by Talk" : "Lösenordsskydda med Talk", "Access control" : "Åtkomstkontroll", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} delad via länk", - "Could not unshare" : "Kunde inte ta bort delning", "Error while sharing" : "Fel vid delning", "Share details could not be loaded for this item." : "Delningsdetaljer kunde inte laddas för detta objekt.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Minst {count} tecken krävs för automatisk ifyllning","Minst {count} tecken krävs för automatisk ifyllning"], @@ -168,9 +167,6 @@ "No users found for {search}" : "Inga användare funna för {search}", "An error occurred (\"{message}\"). Please try again" : "Ett fel uppstod (\"{message}\"). Försök igen", "An error occurred. Please try again" : "Ett fel uppstod. Vänligen försök igen", - "{sharee} (group)" : "{sharee} (grupp)", - "{sharee} (remote)" : "{sharee} (externt)", - "{sharee} (email)" : "{sharee} (e-post)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Dela", "Name or email address..." : "Namn eller e-postadress", @@ -320,6 +316,9 @@ "Error setting expiration date" : "Fel vid val av utgångsdatum", "The public link will expire no later than {days} days after it is created" : "Den offentliga länken kommer sluta gälla inte senare än {days} dagar efter att den skapades", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} delad via länk", + "{sharee} (group)" : "{sharee} (grupp)", + "{sharee} (remote)" : "{sharee} (externt)", + "{sharee} (email)" : "{sharee} (e-post)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Dela med andra personer genom att ange användarnamn, grupp, ett federerat moln-ID eller en e-postadress.", "Share with other people by entering a user or group or a federated cloud ID." : "Dela med andra personer genom att ange användarnamn, grupp eller ett federerat moln-ID.", "Share with other people by entering a user or group or an email address." : "Dela med andra personer genom att ange användarnamn, grupp eller en e-postadress.", @@ -344,6 +343,7 @@ "You are about to grant %s access to your %s account." : "Du håller på att ge %s tillgång till ditt %s-konto.", "Depending on your configuration, this button could also work to trust the domain:" : "Beroende på din konfiguration kan denna knappen också fungera föra att lita på domänen:", "Copy URL" : "Kopiera URL", + "Enable" : "Aktivera", "Please log in before granting %s access to your %s account." : "Logga in innan du ger %s åtkomst till ditt %s konto.", "Further information how to configure this can be found in the %sdocumentation%s." : "Ytterligare information hur du konfigurerar detta finns i %sdokumentationen%s." },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/core/l10n/tr.js b/core/l10n/tr.js index e5c85dfc7a6..dbb1505ac94 100644 --- a/core/l10n/tr.js +++ b/core/l10n/tr.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Bakım kipi etkinleştirildi", "Turned off maintenance mode" : "Bakım kipi devre dışı bırakıldı", "Maintenance mode is kept active" : "Bakım kipi etkin tutuldu", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Bitirmek için zamanlanmış görev bekleniyor (5 saniye sonra yeniden denetlenecek)…", "Updating database schema" : "Veritabanı şeması güncelleniyor", "Updated database" : "Veritabanı güncellendi", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Veritabanı şeması güncellemesi denetleniyor (veritabanının büyüklüğüne bağlı olarak uzun sürebilir)", @@ -160,13 +159,17 @@ OC.L10N.register( "Choose a password for the public link" : "Herkese açık bağlantı için bir parola seçin", "Choose a password for the public link or press the \"Enter\" key" : "Herkese açık bağlantı için bir parola belirtin ya da \"Enter\" tuşuna basın", "Copied!" : "Kopyalandı!", + "Copy link" : "Bağlantıyı kopyala", "Not supported!" : "Desteklenmiyor!", "Press ⌘-C to copy." : "Kopyalamak için ⌘-C tuşlarına basın.", "Press Ctrl-C to copy." : "Kopyalamak için Ctrl-C tuşlarına basın.", + "Unable to create a link share" : "Paylaşım bağlantısı oluşturulamadı", + "Unable to toggle this option" : "Bu seçenek değiştirilemedi", "Resharing is not allowed" : "Yeniden paylaşıma izin verilmiyor", "Share to {name}" : "{name} ile paylaş", - "Copy link" : "Bağlantıyı kopyala", "Link" : "Bağlantı", + "Hide download" : "İndirmeyi gizle", + "Password protection enforced" : "Parola koruması dayatılıyor", "Password protect" : "Parola koruması", "Allow editing" : "Düzenlenebilsin", "Email link to person" : "Bağlantıyı e-posta ile gönder", @@ -174,12 +177,19 @@ OC.L10N.register( "Allow upload and editing" : "Yüklenebilsin ve düzenlenebilsin", "Read only" : "Salt okunur", "File drop (upload only)" : "Dosya bırakma (yalnız yükleme)", + "Expiration date enforced" : "Son kullanma süresi dayatılıyor", "Set expiration date" : "Son kullanma tarihini ayarla", "Expiration" : "Son kullanma", "Expiration date" : "Son kullanma tarihi", "Note to recipient" : "Alıcıya not", + "Unshare" : "Paylaşımdan Kaldır", + "Delete share link" : "Paylaşım bağlantısını sil", + "Add another link" : "Başka bir bağlantı ekle", + "Password protection for links is mandatory" : "Bağlantı için parola koruması zorunludur", "Share link" : "Paylaşma bağlantısı", - "Enable" : "Etkinleştir", + "New share link" : "Yeni paylaşım bağlantısı ", + "Password protect by Talk" : "Talk tarafından parola koruması", + "Could not unshare" : "Paylaşım kaldırılamadı", "Shared with you and the group {group} by {owner}" : "{owner} tarafından sizinle ve {group} ile paylaşılmış", "Shared with you and {circle} by {owner}" : "{owner} tarafından sizinle ve {circle} ile paylaşılmış", "Shared with you and the conversation {conversation} by {owner}" : "{owner} tarafından sizinle ve {conversation} görüşmesi ile paylaştırılmış", @@ -192,16 +202,13 @@ OC.L10N.register( "email" : "e-posta", "conversation" : "görüşme", "shared by {sharer}" : "{sharer} tarafından paylaşıldı", - "Unshare" : "Paylaşımdan Kaldır", "Can reshare" : "Yeniden paylaşabilir", "Can edit" : "Düzenleyebilir", "Can create" : "Ekleyebilir", "Can change" : "Düzenleyebilir", "Can delete" : "Silebilir", - "Password protect by Talk" : "Talk tarafından parola koruması", "Access control" : "Erişim denetimi", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} bağlantı ile paylaşılmış", - "Could not unshare" : "Paylaşım kaldırılamadı", "Error while sharing" : "Paylaşılırken sorun çıktı", "Share details could not be loaded for this item." : "Bu öge için paylaşma ayrıntıları yüklenemedi.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Otomatik tamamlama için en az {count} karakter gereklidir","Otomatik tamamlama için en az {count} karakter gereklidir"], @@ -210,12 +217,10 @@ OC.L10N.register( "No users found for {search}" : "{search} araması sonucunda uygun bir kullanıcı bulunamadı", "An error occurred (\"{message}\"). Please try again" : "Bir sorun çıktı (\"{message}\"). Lütfen yeniden deneyin.", "An error occurred. Please try again" : "Bir sorun çıktı. Lütfen yeniden deneyin", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (uzak)", "{sharee} (remote group)" : "{sharee} (uzak grup)", - "{sharee} (email)" : "{sharee} (e-posta)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (görüşme)", + "Home" : "Giriş", + "Other" : "Diğer", "Share" : "Paylaş", "Name or email address..." : "Ad ya da e-posta adresi...", "Name or federated cloud ID..." : "Ad ya da birleşmiş bulut kodu...", @@ -301,6 +306,7 @@ OC.L10N.register( "Skip to main content" : "Ana içeriğe geç", "Skip to navigation of app" : "Uygulama gezinmesine geç", "More apps" : "Diğer uygulamalar", + "More" : "Diğer", "More apps menu" : "Diğer uygulamalar menüsü", "Search" : "Arama", "Reset search" : "Aramayı sıfırla", @@ -334,8 +340,8 @@ OC.L10N.register( "Two-factor authentication" : "İki aşamalı kimlik doğrulama", "Enhanced security is enabled for your account. Choose a second factor for authentication:" : "Hesabınız için gelişmiş güvenlik etkinleştirildi. Kimlik doğrulaması için bir ikinci aşama seçin:", "Could not load at least one of your enabled two-factor auth methods. Please contact your admin." : "Etkinleştirilmiş iki aşamalı kimlik doğrulaması yöntemlerinden en az biri yüklenemedi. Lütfen yöneticiniz ile görüşün.", - "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "İki aşamalı kimlik doğrulamasının kullanılması zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yardım almak için sistem yöneticiniz ile görüşün.", - "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "İki aşamalı kimlik doğrulamasının kullanılması zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yedek kodlarınızdan birini kullanın ya da yardım almak için sistem yöneticiniz ile görüşün.", + "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "İki aşamalı kimlik doğrulaması kullanımı zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yardım almak için sistem yöneticiniz ile görüşün.", + "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "İki aşamalı kimlik doğrulaması kullanımı zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yedek kodlarınızdan birini kullanın ya da yardım almak için sistem yöneticiniz ile görüşün.", "Use backup code" : "Yedek kodu kullanacağım", "Cancel log in" : "Oturum açmaktan vazgeç", "Error while validating your second factor" : "İkinci aşama doğrulanırken sorun çıktı", @@ -382,6 +388,9 @@ OC.L10N.register( "Error setting expiration date" : "Son kullanma tarihi ayarlanırken sorun çıktı", "The public link will expire no later than {days} days after it is created" : "Herkese açık bağlantı, oluşturulduktan {days} gün sonra kullanımdan kaldırılacak", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} bağlantı ile paylaşılmış", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (uzak)", + "{sharee} (email)" : "{sharee} (e-posta)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Bir kullanıcı, grup, birleşmiş bulut kodu ya da e-posta adresi yazarak başkaları ile paylaşın.", "Share with other people by entering a user or group or a federated cloud ID." : "Bir kullanıcı, grup ya da birleşmiş bulut kodu yazarak başkaları ile paylaşın.", "Share with other people by entering a user or group or an email address." : "Bir kullanıcı, grup ya da e-posta adresi yazarak başkaları ile paylaşın.", @@ -413,6 +422,8 @@ OC.L10N.register( "You are about to grant %s access to your %s account." : "%s erişim iznini %s hesabınız için vermek üzeresiniz.", "Depending on your configuration, this button could also work to trust the domain:" : "Yapılandırmanıza bağlı olarak, bu düğme etki alanına güvenmek için de kullanılabilir:", "Copy URL" : "Adresi Kopyala", + "Enable" : "Etkinleştir", + "{sharee} (conversation)" : "{sharee} (görüşme)", "Please log in before granting %s access to your %s account." : "Lütfen %s erişim izni %s vermeden önce oturum açın.", "Further information how to configure this can be found in the %sdocumentation%s." : "Bu ayar ile ilgili ayrıntılı bilgi almak için %sbelgelere%s bakabilirsiniz." }, diff --git a/core/l10n/tr.json b/core/l10n/tr.json index a97bd488941..d5ccee96d57 100644 --- a/core/l10n/tr.json +++ b/core/l10n/tr.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Bakım kipi etkinleştirildi", "Turned off maintenance mode" : "Bakım kipi devre dışı bırakıldı", "Maintenance mode is kept active" : "Bakım kipi etkin tutuldu", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Bitirmek için zamanlanmış görev bekleniyor (5 saniye sonra yeniden denetlenecek)…", "Updating database schema" : "Veritabanı şeması güncelleniyor", "Updated database" : "Veritabanı güncellendi", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Veritabanı şeması güncellemesi denetleniyor (veritabanının büyüklüğüne bağlı olarak uzun sürebilir)", @@ -158,13 +157,17 @@ "Choose a password for the public link" : "Herkese açık bağlantı için bir parola seçin", "Choose a password for the public link or press the \"Enter\" key" : "Herkese açık bağlantı için bir parola belirtin ya da \"Enter\" tuşuna basın", "Copied!" : "Kopyalandı!", + "Copy link" : "Bağlantıyı kopyala", "Not supported!" : "Desteklenmiyor!", "Press ⌘-C to copy." : "Kopyalamak için ⌘-C tuşlarına basın.", "Press Ctrl-C to copy." : "Kopyalamak için Ctrl-C tuşlarına basın.", + "Unable to create a link share" : "Paylaşım bağlantısı oluşturulamadı", + "Unable to toggle this option" : "Bu seçenek değiştirilemedi", "Resharing is not allowed" : "Yeniden paylaşıma izin verilmiyor", "Share to {name}" : "{name} ile paylaş", - "Copy link" : "Bağlantıyı kopyala", "Link" : "Bağlantı", + "Hide download" : "İndirmeyi gizle", + "Password protection enforced" : "Parola koruması dayatılıyor", "Password protect" : "Parola koruması", "Allow editing" : "Düzenlenebilsin", "Email link to person" : "Bağlantıyı e-posta ile gönder", @@ -172,12 +175,19 @@ "Allow upload and editing" : "Yüklenebilsin ve düzenlenebilsin", "Read only" : "Salt okunur", "File drop (upload only)" : "Dosya bırakma (yalnız yükleme)", + "Expiration date enforced" : "Son kullanma süresi dayatılıyor", "Set expiration date" : "Son kullanma tarihini ayarla", "Expiration" : "Son kullanma", "Expiration date" : "Son kullanma tarihi", "Note to recipient" : "Alıcıya not", + "Unshare" : "Paylaşımdan Kaldır", + "Delete share link" : "Paylaşım bağlantısını sil", + "Add another link" : "Başka bir bağlantı ekle", + "Password protection for links is mandatory" : "Bağlantı için parola koruması zorunludur", "Share link" : "Paylaşma bağlantısı", - "Enable" : "Etkinleştir", + "New share link" : "Yeni paylaşım bağlantısı ", + "Password protect by Talk" : "Talk tarafından parola koruması", + "Could not unshare" : "Paylaşım kaldırılamadı", "Shared with you and the group {group} by {owner}" : "{owner} tarafından sizinle ve {group} ile paylaşılmış", "Shared with you and {circle} by {owner}" : "{owner} tarafından sizinle ve {circle} ile paylaşılmış", "Shared with you and the conversation {conversation} by {owner}" : "{owner} tarafından sizinle ve {conversation} görüşmesi ile paylaştırılmış", @@ -190,16 +200,13 @@ "email" : "e-posta", "conversation" : "görüşme", "shared by {sharer}" : "{sharer} tarafından paylaşıldı", - "Unshare" : "Paylaşımdan Kaldır", "Can reshare" : "Yeniden paylaşabilir", "Can edit" : "Düzenleyebilir", "Can create" : "Ekleyebilir", "Can change" : "Düzenleyebilir", "Can delete" : "Silebilir", - "Password protect by Talk" : "Talk tarafından parola koruması", "Access control" : "Erişim denetimi", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} bağlantı ile paylaşılmış", - "Could not unshare" : "Paylaşım kaldırılamadı", "Error while sharing" : "Paylaşılırken sorun çıktı", "Share details could not be loaded for this item." : "Bu öge için paylaşma ayrıntıları yüklenemedi.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Otomatik tamamlama için en az {count} karakter gereklidir","Otomatik tamamlama için en az {count} karakter gereklidir"], @@ -208,12 +215,10 @@ "No users found for {search}" : "{search} araması sonucunda uygun bir kullanıcı bulunamadı", "An error occurred (\"{message}\"). Please try again" : "Bir sorun çıktı (\"{message}\"). Lütfen yeniden deneyin.", "An error occurred. Please try again" : "Bir sorun çıktı. Lütfen yeniden deneyin", - "{sharee} (group)" : "{sharee} (grup)", - "{sharee} (remote)" : "{sharee} (uzak)", "{sharee} (remote group)" : "{sharee} (uzak grup)", - "{sharee} (email)" : "{sharee} (e-posta)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (görüşme)", + "Home" : "Giriş", + "Other" : "Diğer", "Share" : "Paylaş", "Name or email address..." : "Ad ya da e-posta adresi...", "Name or federated cloud ID..." : "Ad ya da birleşmiş bulut kodu...", @@ -299,6 +304,7 @@ "Skip to main content" : "Ana içeriğe geç", "Skip to navigation of app" : "Uygulama gezinmesine geç", "More apps" : "Diğer uygulamalar", + "More" : "Diğer", "More apps menu" : "Diğer uygulamalar menüsü", "Search" : "Arama", "Reset search" : "Aramayı sıfırla", @@ -332,8 +338,8 @@ "Two-factor authentication" : "İki aşamalı kimlik doğrulama", "Enhanced security is enabled for your account. Choose a second factor for authentication:" : "Hesabınız için gelişmiş güvenlik etkinleştirildi. Kimlik doğrulaması için bir ikinci aşama seçin:", "Could not load at least one of your enabled two-factor auth methods. Please contact your admin." : "Etkinleştirilmiş iki aşamalı kimlik doğrulaması yöntemlerinden en az biri yüklenemedi. Lütfen yöneticiniz ile görüşün.", - "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "İki aşamalı kimlik doğrulamasının kullanılması zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yardım almak için sistem yöneticiniz ile görüşün.", - "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "İki aşamalı kimlik doğrulamasının kullanılması zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yedek kodlarınızdan birini kullanın ya da yardım almak için sistem yöneticiniz ile görüşün.", + "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "İki aşamalı kimlik doğrulaması kullanımı zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yardım almak için sistem yöneticiniz ile görüşün.", + "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "İki aşamalı kimlik doğrulaması kullanımı zorunlu kılınmış ancak hesabınız için yapılandırılmamış. Yedek kodlarınızdan birini kullanın ya da yardım almak için sistem yöneticiniz ile görüşün.", "Use backup code" : "Yedek kodu kullanacağım", "Cancel log in" : "Oturum açmaktan vazgeç", "Error while validating your second factor" : "İkinci aşama doğrulanırken sorun çıktı", @@ -380,6 +386,9 @@ "Error setting expiration date" : "Son kullanma tarihi ayarlanırken sorun çıktı", "The public link will expire no later than {days} days after it is created" : "Herkese açık bağlantı, oluşturulduktan {days} gün sonra kullanımdan kaldırılacak", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} bağlantı ile paylaşılmış", + "{sharee} (group)" : "{sharee} (grup)", + "{sharee} (remote)" : "{sharee} (uzak)", + "{sharee} (email)" : "{sharee} (e-posta)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Bir kullanıcı, grup, birleşmiş bulut kodu ya da e-posta adresi yazarak başkaları ile paylaşın.", "Share with other people by entering a user or group or a federated cloud ID." : "Bir kullanıcı, grup ya da birleşmiş bulut kodu yazarak başkaları ile paylaşın.", "Share with other people by entering a user or group or an email address." : "Bir kullanıcı, grup ya da e-posta adresi yazarak başkaları ile paylaşın.", @@ -411,6 +420,8 @@ "You are about to grant %s access to your %s account." : "%s erişim iznini %s hesabınız için vermek üzeresiniz.", "Depending on your configuration, this button could also work to trust the domain:" : "Yapılandırmanıza bağlı olarak, bu düğme etki alanına güvenmek için de kullanılabilir:", "Copy URL" : "Adresi Kopyala", + "Enable" : "Etkinleştir", + "{sharee} (conversation)" : "{sharee} (görüşme)", "Please log in before granting %s access to your %s account." : "Lütfen %s erişim izni %s vermeden önce oturum açın.", "Further information how to configure this can be found in the %sdocumentation%s." : "Bu ayar ile ilgili ayrıntılı bilgi almak için %sbelgelere%s bakabilirsiniz." },"pluralForm" :"nplurals=2; plural=(n > 1);" diff --git a/core/l10n/uk.js b/core/l10n/uk.js index c5013f0ae59..f677957e757 100644 --- a/core/l10n/uk.js +++ b/core/l10n/uk.js @@ -131,7 +131,9 @@ OC.L10N.register( "Set expiration date" : "Встановити термін дії", "Expiration" : "Закінчення", "Expiration date" : "Термін дії", + "Unshare" : "Закрити доступ", "Share link" : "Поділитись посиланням", + "Could not unshare" : "Неможливо припинити ділитися файлом", "Shared with you and the group {group} by {owner}" : " {owner} опублікував для Вас та для групи {group}", "Shared with you by {owner}" : "{owner} опублікував для Вас", "Choose a password for the mail share" : "Встановіть пароль на спільне посилання через електронну пошту", @@ -139,22 +141,17 @@ OC.L10N.register( "remote" : "Віддалений", "email" : "електронна пошта", "shared by {sharer}" : "поділився {sharer}", - "Unshare" : "Закрити доступ", "Can reshare" : "можна ділитися з іншими", "Can edit" : "може редагувати", "Can create" : "Можна створити", "Can change" : "можна змінити", "Can delete" : "можна видалити", "Access control" : "контроль доступу", - "Could not unshare" : "Неможливо припинити ділитися файлом", "Error while sharing" : "Помилка під час публікації", "Share details could not be loaded for this item." : "Неможливо отримати докладну інформацію щодо цього спільного ресурсу", "No users or groups found for {search}" : "Не знайдено груп або користувачів за пошуком {search}", "No users found for {search}" : "Не знайдено жодного користувача для {search}", "An error occurred. Please try again" : "Сталася помилка. Спробуйте ще раз", - "{sharee} (group)" : "{sharee} (група)", - "{sharee} (remote)" : "{sharee} (віддалений)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Поділитися", "Name or email address..." : "Ім'я або адреса електронної пошти...", @@ -259,6 +256,9 @@ OC.L10N.register( "Updated \"%s\" to %s" : "Оновлено \"%s\" до %s", "Error setting expiration date" : "Помилка при встановленні терміну дії", "The public link will expire no later than {days} days after it is created" : "Доступ до опублікованого посилання буде припинено не пізніше ніж через {days} днів з моменту створення", + "{sharee} (group)" : "{sharee} (група)", + "{sharee} (remote)" : "{sharee} (віддалений)", + "{sharee} (email)" : "{sharee} (email)", "The specified document has not been found on the server." : "Не вдалось знайти вказаний документ на сервері.", "You can click here to return to %s." : "Ви можете натиснути тут для повернення до %s.", "Wrong password. Reset it?" : "Невірний пароль. Скинути його?", diff --git a/core/l10n/uk.json b/core/l10n/uk.json index 5eb7b3b93c2..97e46ecea42 100644 --- a/core/l10n/uk.json +++ b/core/l10n/uk.json @@ -129,7 +129,9 @@ "Set expiration date" : "Встановити термін дії", "Expiration" : "Закінчення", "Expiration date" : "Термін дії", + "Unshare" : "Закрити доступ", "Share link" : "Поділитись посиланням", + "Could not unshare" : "Неможливо припинити ділитися файлом", "Shared with you and the group {group} by {owner}" : " {owner} опублікував для Вас та для групи {group}", "Shared with you by {owner}" : "{owner} опублікував для Вас", "Choose a password for the mail share" : "Встановіть пароль на спільне посилання через електронну пошту", @@ -137,22 +139,17 @@ "remote" : "Віддалений", "email" : "електронна пошта", "shared by {sharer}" : "поділився {sharer}", - "Unshare" : "Закрити доступ", "Can reshare" : "можна ділитися з іншими", "Can edit" : "може редагувати", "Can create" : "Можна створити", "Can change" : "можна змінити", "Can delete" : "можна видалити", "Access control" : "контроль доступу", - "Could not unshare" : "Неможливо припинити ділитися файлом", "Error while sharing" : "Помилка під час публікації", "Share details could not be loaded for this item." : "Неможливо отримати докладну інформацію щодо цього спільного ресурсу", "No users or groups found for {search}" : "Не знайдено груп або користувачів за пошуком {search}", "No users found for {search}" : "Не знайдено жодного користувача для {search}", "An error occurred. Please try again" : "Сталася помилка. Спробуйте ще раз", - "{sharee} (group)" : "{sharee} (група)", - "{sharee} (remote)" : "{sharee} (віддалений)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Поділитися", "Name or email address..." : "Ім'я або адреса електронної пошти...", @@ -257,6 +254,9 @@ "Updated \"%s\" to %s" : "Оновлено \"%s\" до %s", "Error setting expiration date" : "Помилка при встановленні терміну дії", "The public link will expire no later than {days} days after it is created" : "Доступ до опублікованого посилання буде припинено не пізніше ніж через {days} днів з моменту створення", + "{sharee} (group)" : "{sharee} (група)", + "{sharee} (remote)" : "{sharee} (віддалений)", + "{sharee} (email)" : "{sharee} (email)", "The specified document has not been found on the server." : "Не вдалось знайти вказаний документ на сервері.", "You can click here to return to %s." : "Ви можете натиснути тут для повернення до %s.", "Wrong password. Reset it?" : "Невірний пароль. Скинути його?", diff --git a/core/l10n/vi.js b/core/l10n/vi.js index a6615109218..a3d4928fff2 100644 --- a/core/l10n/vi.js +++ b/core/l10n/vi.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "Bật chế độ bảo trì", "Turned off maintenance mode" : "Tắt chế độ bảo trì", "Maintenance mode is kept active" : "Chế độ bảo trì đang được kích hoạt", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Chờ hoàn tất cron (kiểm tra lại trong 5s nữa)...", "Updating database schema" : "Đang cập nhật lược đồ cơ sở dữ liệu", "Updated database" : "Cơ sở dữ liệu đã được cập nhật", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Đang kiểm tra xem lược đồ cơ sở dữ liệu có thể được cập nhật hay không (việc này có thể mất nhiều thời gian do phụ thuộc vào kích cỡ của cơ sở dữ liệu)", @@ -132,8 +131,10 @@ OC.L10N.register( "Set expiration date" : "Đặt ngày kết thúc", "Expiration" : "Hết hạn", "Expiration date" : "Ngày kết thúc", + "Unshare" : "Bỏ chia sẻ", "Share link" : "Chia sẻ liên kết", - "Enable" : "Bật", + "Password protect by Talk" : "Mật khẩu bảo vệ bằng đàm thoại", + "Could not unshare" : "Không thể chia sẻ", "Shared with you and the group {group} by {owner}" : "Đã được chia sẽ với bạn và nhóm {group} bởi {owner}", "Shared with you by {owner}" : "Đã được chia sẽ bởi {owner}", "Choose a password for the mail share" : "Chọn một mật khẩu để chia sẻ qua mail", @@ -142,15 +143,12 @@ OC.L10N.register( "email" : "Thư điện tử", "conversation" : "đàm thoại", "shared by {sharer}" : "được chia sẻ bởi {sharer}", - "Unshare" : "Bỏ chia sẻ", "Can reshare" : "Có thể chia sẻ lại", "Can edit" : "Có thể chỉnh sửa", "Can create" : "Có thể tạo", "Can change" : "Có thể thay đổi", "Can delete" : "Có thể xóa", - "Password protect by Talk" : "Mật khẩu bảo vệ bằng đàm thoại", "Access control" : "Kiểm soát truy cập", - "Could not unshare" : "Không thể chia sẻ", "Error while sharing" : "Lỗi trong quá trình chia sẻ", "Share details could not be loaded for this item." : "Các chi tiết chia sẻ không thể được nạp đối với mục này", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Cần ít nhất {count} ký tự cho tự động hoàn thành"], @@ -159,9 +157,6 @@ OC.L10N.register( "No users found for {search}" : "Không tìm thấy người dùng cho {search}", "An error occurred (\"{message}\"). Please try again" : "Đã xảy ra lỗi (\"{message}\"). Hãy thử lại", "An error occurred. Please try again" : "Có lỗi vừa xảy ra. Xin vui lòng thử lại", - "{sharee} (group)" : "{sharee} (nhóm)", - "{sharee} (remote)" : "{sharee} (từ xa)", - "{sharee} (email)" : "{sharee} (thư điện tử)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Chia sẻ", "Name or email address..." : "Tên hoặc địa chỉ email.", @@ -292,6 +287,9 @@ OC.L10N.register( "Error setting expiration date" : "Lỗi cấu hình ngày kết thúc", "The public link will expire no later than {days} days after it is created" : "Liên kết công khai sẽ hết hạn sau {days} ngày sau khi được tạo", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} chia sẻ qua liên kết", + "{sharee} (group)" : "{sharee} (nhóm)", + "{sharee} (remote)" : "{sharee} (từ xa)", + "{sharee} (email)" : "{sharee} (thư điện tử)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Chia sẻ với người khác bằng cách nhập tên người dùng hoặc tên nhóm, ID đám mây liên kết hoặc địa chỉ email.", "Share with other people by entering a user or group or a federated cloud ID." : "Chia sẻ với người khác bằng cách nhập tên người dùng hoặc tên nhóm, ID đám mây liên kết.", "Share with other people by entering a user or group or an email address." : "Chia sẻ với người khác bằng cách nhập tên người dùng hoặc tên nhóm, hoặc địa chỉ email.", @@ -308,6 +306,7 @@ OC.L10N.register( "Thank you for your patience." : "Cảm ơn sự kiên nhẫn của bạn.", "Back to log in" : "Trở lại trang đăng nhập", "You are about to grant %s access to your %s account." : "Bạn sắp được phép %s truy nhập tới tài khoản %s của bạn.", - "Depending on your configuration, this button could also work to trust the domain:" : "Phụ thuộc vào cấu hình của bạn, nút lệnh này có thể hoạt động để bảo đảm tin tưởng tên miền:" + "Depending on your configuration, this button could also work to trust the domain:" : "Phụ thuộc vào cấu hình của bạn, nút lệnh này có thể hoạt động để bảo đảm tin tưởng tên miền:", + "Enable" : "Bật" }, "nplurals=1; plural=0;"); diff --git a/core/l10n/vi.json b/core/l10n/vi.json index cee3000c91a..ba2e77671b2 100644 --- a/core/l10n/vi.json +++ b/core/l10n/vi.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "Bật chế độ bảo trì", "Turned off maintenance mode" : "Tắt chế độ bảo trì", "Maintenance mode is kept active" : "Chế độ bảo trì đang được kích hoạt", - "Waiting for cron to finish (checks again in 5 seconds) …" : "Chờ hoàn tất cron (kiểm tra lại trong 5s nữa)...", "Updating database schema" : "Đang cập nhật lược đồ cơ sở dữ liệu", "Updated database" : "Cơ sở dữ liệu đã được cập nhật", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Đang kiểm tra xem lược đồ cơ sở dữ liệu có thể được cập nhật hay không (việc này có thể mất nhiều thời gian do phụ thuộc vào kích cỡ của cơ sở dữ liệu)", @@ -130,8 +129,10 @@ "Set expiration date" : "Đặt ngày kết thúc", "Expiration" : "Hết hạn", "Expiration date" : "Ngày kết thúc", + "Unshare" : "Bỏ chia sẻ", "Share link" : "Chia sẻ liên kết", - "Enable" : "Bật", + "Password protect by Talk" : "Mật khẩu bảo vệ bằng đàm thoại", + "Could not unshare" : "Không thể chia sẻ", "Shared with you and the group {group} by {owner}" : "Đã được chia sẽ với bạn và nhóm {group} bởi {owner}", "Shared with you by {owner}" : "Đã được chia sẽ bởi {owner}", "Choose a password for the mail share" : "Chọn một mật khẩu để chia sẻ qua mail", @@ -140,15 +141,12 @@ "email" : "Thư điện tử", "conversation" : "đàm thoại", "shared by {sharer}" : "được chia sẻ bởi {sharer}", - "Unshare" : "Bỏ chia sẻ", "Can reshare" : "Có thể chia sẻ lại", "Can edit" : "Có thể chỉnh sửa", "Can create" : "Có thể tạo", "Can change" : "Có thể thay đổi", "Can delete" : "Có thể xóa", - "Password protect by Talk" : "Mật khẩu bảo vệ bằng đàm thoại", "Access control" : "Kiểm soát truy cập", - "Could not unshare" : "Không thể chia sẻ", "Error while sharing" : "Lỗi trong quá trình chia sẻ", "Share details could not be loaded for this item." : "Các chi tiết chia sẻ không thể được nạp đối với mục này", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["Cần ít nhất {count} ký tự cho tự động hoàn thành"], @@ -157,9 +155,6 @@ "No users found for {search}" : "Không tìm thấy người dùng cho {search}", "An error occurred (\"{message}\"). Please try again" : "Đã xảy ra lỗi (\"{message}\"). Hãy thử lại", "An error occurred. Please try again" : "Có lỗi vừa xảy ra. Xin vui lòng thử lại", - "{sharee} (group)" : "{sharee} (nhóm)", - "{sharee} (remote)" : "{sharee} (từ xa)", - "{sharee} (email)" : "{sharee} (thư điện tử)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", "Share" : "Chia sẻ", "Name or email address..." : "Tên hoặc địa chỉ email.", @@ -290,6 +285,9 @@ "Error setting expiration date" : "Lỗi cấu hình ngày kết thúc", "The public link will expire no later than {days} days after it is created" : "Liên kết công khai sẽ hết hạn sau {days} ngày sau khi được tạo", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} chia sẻ qua liên kết", + "{sharee} (group)" : "{sharee} (nhóm)", + "{sharee} (remote)" : "{sharee} (từ xa)", + "{sharee} (email)" : "{sharee} (thư điện tử)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "Chia sẻ với người khác bằng cách nhập tên người dùng hoặc tên nhóm, ID đám mây liên kết hoặc địa chỉ email.", "Share with other people by entering a user or group or a federated cloud ID." : "Chia sẻ với người khác bằng cách nhập tên người dùng hoặc tên nhóm, ID đám mây liên kết.", "Share with other people by entering a user or group or an email address." : "Chia sẻ với người khác bằng cách nhập tên người dùng hoặc tên nhóm, hoặc địa chỉ email.", @@ -306,6 +304,7 @@ "Thank you for your patience." : "Cảm ơn sự kiên nhẫn của bạn.", "Back to log in" : "Trở lại trang đăng nhập", "You are about to grant %s access to your %s account." : "Bạn sắp được phép %s truy nhập tới tài khoản %s của bạn.", - "Depending on your configuration, this button could also work to trust the domain:" : "Phụ thuộc vào cấu hình của bạn, nút lệnh này có thể hoạt động để bảo đảm tin tưởng tên miền:" + "Depending on your configuration, this button could also work to trust the domain:" : "Phụ thuộc vào cấu hình của bạn, nút lệnh này có thể hoạt động để bảo đảm tin tưởng tên miền:", + "Enable" : "Bật" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/core/l10n/zh_CN.js b/core/l10n/zh_CN.js index e6de190ac2b..39b0b8a58c9 100644 --- a/core/l10n/zh_CN.js +++ b/core/l10n/zh_CN.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "启用维护模式", "Turned off maintenance mode" : "关闭维护模式", "Maintenance mode is kept active" : "维护模式已启用", - "Waiting for cron to finish (checks again in 5 seconds) …" : "等待cron进程结束(5秒后重新检测) …", "Updating database schema" : "正在更新数据库结构", "Updated database" : "数据库已更新", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "检查数据库结构是否可以更新 (这可能需要很长的时间, 这取决于数据库大小)", @@ -104,8 +103,8 @@ OC.L10N.register( "({count} selected)" : "(选择了 {count} 个)", "Error loading file exists template" : "加载文件存在性模板失败", "Pending" : "等待", - "Copy to {folder}" : "复制{文件夹}", - "Move to {folder}" : "移动{文件夹}", + "Copy to {folder}" : "复制到 {folder}", + "Move to {folder}" : "移动到 {folder}", "New in" : "新品", "View changelog" : "查看更新记录", "Very weak password" : "非常弱的密码", @@ -122,6 +121,9 @@ OC.L10N.register( "The PHP module \"fileinfo\" is missing. It is strongly recommended to enable this module to get the best results with MIME type detection." : "未找到 PHP 的 \"fileinfo\" 模块。强烈推荐启用该模块,从而获得更好的 MIME 类型探测结果。", "{name} below version {version} is installed, for stability and performance reasons it is recommended to update to a newer {name} version." : "{name} 已安装 {version} 版本,出于稳定和性能的考虑,建议更新到 {name} 版本。", "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 noopener\" href=\"{docLink}\">documentation ↗</a> for more information." : "已禁用事务性文件锁定,这可能在竞争条件下导致问题。在 config.php 中启用 \"filelocking.enabled\" 可以避免此问题。详情查阅 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档 ↗</a>。", + "If your installation is not installed at 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 (suggestion: \"{suggestedOverwriteCliURL}\")" : "如果没有将 Nextcloud 安装到域名根目录并使用系统计划任务,生成超链接就会出现问题。为避免此问题,请在 config.php 配置文件中将 \"overwrite.cli.url\" 设置为你 Nextcloud 安装的路径。(建议:\"{suggestedOverwriteCliURL}\")", + "It was not possible to execute the cron job via CLI. The following technical errors have appeared:" : "无法通过 CLI 执行计划任务,请查看以下技术错误:", + "Last background job execution ran {relativeTime}. Something seems wrong." : "最近一次执行后台任务运行时间为 {relativeTime},似乎哪里出了问题。", "Check the background job settings" : "请检查后台任务设置", "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." : "此服务器没有可用的互联网连接:多个节点无法访问。这意味着某些功能比如挂载外部存储,更新通知以及安装第三方应用将无法工作。远程访问文件和发送通知邮件可能也不工作。启用这台服务器上的互联网连接以享用所有功能。", "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>." : "内存缓存未配置,为了提升使用体验,请尽量配置内存缓存。更多信息请参见<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档</a>。", @@ -130,22 +132,33 @@ OC.L10N.register( "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "反向代理头部配置错误,或者您正在通过可信的代理访问 Nextcloud。如果您不是通过可信代理访问 Nextcloud,这是一个安全问题,它允许攻击者通过伪装 IP 地址访问 Nextcloud。更多信息请查看<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档</a>。", "Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached 当前配置为分布式缓存, 但是当前安装的 PHP 模块是 \"memcache\". \\OC\\Memcache\\Memcached 仅支持 \"memcached\" 而不是 \"memcache\". 点击 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{wikiLink}\">memcached wiki </a>了解两者的差别。", "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "一些文件没有通过完整性检查。了解如何解决该问题请查看我们的 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档</a>。(<a href=\"{codeIntegrityDownloadEndpoint}\">无效文件列表…</a> / <a href=\"{rescanEndpoint}\">重新扫描…</a>)", + "The PHP OPcache module is not loaded. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to load it into your PHP installation." : "PHP 的 OPcache 模块未载入。<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">推荐开启获得更好的性能</a>。", "The PHP OPcache is not properly configured. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to use the following settings in the <code>php.ini</code>:" : "PHP 的组件 OPcache 没有正确配置。 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">为了提供更好的性能</a>,我们建议在 <code>php.ini</code>中使用下列设置:", "The PHP function \"set_time_limit\" is not available. This could result in scripts being halted mid-execution, breaking your installation. Enabling this function is strongly recommended." : "PHP函数“set_time_limit”不可用。 这可能会导致脚本在执行过程中暂停,从而导致安装中断。 我们强烈建议启用此功能。", "Your PHP does not have FreeType support, resulting in breakage of profile pictures and the settings interface." : "您的 PHP 没有 FreeType 支持,导致配置文件图片和设置界面中断。", "Missing index \"{indexName}\" in table \"{tableName}\"." : "在数据表 \"{tableName}\" 中无法找到索引 \"{indexName}\" .", + "The database is missing some indexes. Due to the fact that adding indexes on big tables could take some time they were not added automatically. By running \"occ db:add-missing-indices\" those missing indexes could be added manually while the instance keeps running. Once the indexes are added queries to those tables are usually much faster." : "数据库丢失了一些索引。由于给大的数据表添加索引会耗费一些时间,因此程序没有自动对其进行修复。您可以在 Nextcloud 运行时通过命令行手动执行 \"occ db:add-missing-indices\" 命令修复丢失的索引。索引修复后会大大提高相应表的查询速度。", + "SQLite is currently being used as the backend database. For larger installations we recommend that you switch to a different database backend." : "当前正在使用 SQLite 作为后端数据库。多用户使用时,推荐您改用其他的数据库。", + "This is particularly recommended when using the desktop client for file synchronisation." : "特别推荐使用桌面客户端同步的用户选择。", + "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation ↗</a>." : "迁移到其他数据库,使用命令:'occ db:convert-type' 或查阅 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档↗</a>。", + "Use of the the built in php mailer is no longer supported. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">Please update your email server settings ↗<a/>." : "PHP 内建的邮件发送器已不再受支持。<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">请更新你的 E-mail 服务器设置↗<a/>。", "The PHP memory limit is below the recommended value of 512MB." : "PHP内存限制低于建议值512MB.", + "Some app directories are owned by a different user than the web server one. This may be the case if apps have been installed manually. Check the permissions of the following app directories:" : "有些应用程序目录是由与 Web 服务器不同的用户拥有的。如果应用程序是手动安装的,情况可能是这样的。检查以下应用程序目录的权限:", "Error occurred while checking server setup" : "检查服务器设置时出错", "Your data directory and files are probably accessible from the Internet. The .htaccess file is not working. It is strongly recommended that you configure your web server so that the data directory is no longer accessible, or move the data directory outside the web server document root." : "您的数据目录和文件可以从互联网直接访问。.htaccess 文件不起作用。强烈建议您配置 Web 服务器,以便数据目录不再可访问,或者你可以将数据目录移动到 Web 服务器文档根目录。", "The \"{header}\" HTTP header is not set to \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "HTTP 请求头 \"{header}\" 没有配置为 \"{expected}\"。这是一个潜在的安全或隐私风险, 我们建议您调整这项设置.", "The \"{header}\" HTTP header is not set to \"{expected}\". Some features might not work correctly, as it is recommended to adjust this setting accordingly." : "HTTP 请求头 \"{header}\" 没有配置为 \"{expected}\"。某些功能可能无法正常工作,因此建议相应地调整此设置。", + "The \"{header}\" HTTP header doesn't contain \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "HTTP 头 \"{header}\" 未包含 \"{expected}\"。这是一种潜在的安全或隐私风险,因此推荐调整此项设置。", + "The \"{header}\" HTTP header is not set to \"{val1}\", \"{val2}\", \"{val3}\", \"{val4}\" or \"{val5}\". This can leak referer information. See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C Recommendation ↗</a>." : "HTTP 头 \"{header}\" 未设置成 \"{val1}\",\"{val2}\",\"{val3}\",\"{val4}\" 或 \"{val5}\"。这会泄露更多的信息。请查阅 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C 建议↗</a>。", "The \"Strict-Transport-Security\" HTTP header is not set to at least \"{seconds}\" seconds. For enhanced security, it is recommended to enable HSTS as described in the <a href=\"{docUrl}\" rel=\"noreferrer noopener\">security tips ↗</a>." : "HTTP的请求头 \"Strict-Transport-Security\" 未设置为至少 \"{seconds}\" 秒. 为了提高安全性,建议参照<a href=\"{docUrl}\" rel=\"noreferrer noopener\">security tips ↗</a>中的说明启用HSTS.", + "Accessing site insecurely via HTTP. You are strongly adviced to set up your server to require HTTPS instead, as described in the <a href=\"{docUrl}\">security tips ↗</a>." : "通过 HTTP 访问网站不安全。强烈建议您将服务器设置成 HTTPS 协议,请查阅 <a href=\"{docUrl}\">安全贴士↗</a>。", "Shared" : "已共享", "Shared with" : "共享给", "Shared by" : "共享人", "Choose a password for the public link" : "为公开链接设置密码", "Choose a password for the public link or press the \"Enter\" key" : "为公开链接设置密码, 或按 \"回车\" 键", "Copied!" : "已经复制!", + "Copy link" : "复制链接", "Not supported!" : "无法支持!", "Press ⌘-C to copy." : "按 ⌘ + C 进行复制.", "Press Ctrl-C to copy." : "按 Ctrl + C 进行复制.", @@ -162,26 +175,30 @@ OC.L10N.register( "Set expiration date" : "设置过期日期", "Expiration" : "过期", "Expiration date" : "过期日期", + "Note to recipient" : "备注", + "Unshare" : "取消共享", "Share link" : "共享链接", - "Enable" : "启用", + "Password protect by Talk" : "通过 Talk 保护密码", + "Could not unshare" : "无法共享", "Shared with you and the group {group} by {owner}" : "{owner} 共享给您及 {group} 分组", "Shared with you and {circle} by {owner}" : "{owner} 共享给您及 {circle}", "Shared with you and the conversation {conversation} by {owner}" : "{owner} 共享给您及对话 {conversation}", + "Shared with you in a conversation by {owner}" : "由 {owner} 通过一个对话与你分享", "Shared with you by {owner}" : "{owner} 共享给您", "Choose a password for the mail share" : "为电子邮件共享选择一个密码", "group" : "群组", "remote" : "外部", "remote group" : "远程群组", "email" : "邮件", + "conversation" : "对话", "shared by {sharer}" : "由 {sharer} 共享", - "Unshare" : "取消共享", "Can reshare" : "可以再次共享", "Can edit" : "可以编辑", "Can create" : "可以创建", "Can change" : "可以修改", "Can delete" : "可以删除", "Access control" : "访问控制", - "Could not unshare" : "无法共享", + "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} 通过链接共享", "Error while sharing" : "共享时出错", "Share details could not be loaded for this item." : "无法加载这个项目的共享详情.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["{count}字符需要自动完成"], @@ -190,9 +207,7 @@ OC.L10N.register( "No users found for {search}" : "没有找到 {search} 用户", "An error occurred (\"{message}\"). Please try again" : "发生错误 (\"{message}\"). 请重试", "An error occurred. Please try again" : "发生错误. 请重试", - "{sharee} (group)" : "{sharee} (分组)", - "{sharee} (remote)" : "{sharee} (外部)", - "{sharee} (email)" : "{sharee} (邮件)", + "{sharee} (remote group)" : "{sharee}(远程组)", "{sharee} ({type}, {owner})" : "{share}({type},{owner})", "Share" : "共享", "Name or email address..." : "姓名或电子邮件地址...", @@ -235,6 +250,8 @@ OC.L10N.register( "Help" : "帮助", "Access forbidden" : "访问禁止", "File not found" : "文件未找到", + "The document could not be found on the server. Maybe the share was deleted or has expired?" : "服务器上找不到该文档。可能此共享已被删除或过期。", + "Back to %s" : "返回 %s", "Internal Server Error" : "内部服务器错误", "The server was unable to complete your request." : "服务器不能完成你的请求。", "If this happens again, please send the technical details below to the server administrator." : "如果再次发生,请在下方将技术详情发送给服务器管理员。", @@ -274,6 +291,8 @@ OC.L10N.register( "Need help?" : "需要帮助?", "See the documentation" : "查看文档", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "对于正确的操作, 该应用需要使用 JavaScript. 请 {linkstart}启用 JavaScript{linkend}, 并重新加载页面.", + "Skip to main content" : "跳过主内容", + "Skip to navigation of app" : "跳过应用向导", "More apps" : "更多的应用程序", "More apps menu" : "更多的应用菜单", "Search" : "搜索", @@ -294,22 +313,30 @@ OC.L10N.register( "Forgot password?" : "忘记密码?", "Back to login" : "返回登录", "Connect to your account" : "连接您的账户", + "Please log in before granting %1$s access to your %2$s account." : "在授权 %1$s 访问您的 %2$s 账户之前,请先登录。", "App token" : "App 令牌", "Grant access" : "授权访问", "Alternative log in using app token" : "使用应用程序令牌替代登录", "Account access" : "账户访问", + "You are about to grant %1$s access to your %2$s account." : "您正在授权 %1$s 访问您的 %2$s 账户。", "Redirecting …" : "正在跳转 …", "New password" : "新密码", "New Password" : "新密码", "This share is password-protected" : "这个共享是被密码保护的", "The password is wrong. Try again." : "密码错误.请重试.", "Two-factor authentication" : "双重认证", + "Enhanced security is enabled for your account. Choose a second factor for authentication:" : "您的账户已启用安全增强。请选择第二种验证方式。", + "Could not load at least one of your enabled two-factor auth methods. Please contact your admin." : "无法载入你启用的任何双因素验证方法。请联系管理员。", + "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "双因素验证是强制性的,但你的账户似乎未做配置。请联系管理员获得支持。", + "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "双因素验证是强制性的,但你的账户似乎未做配置。使用你的备份代码登录或求助管理员。", "Use backup code" : "使用备用口令", "Cancel log in" : "取消登录", "Error while validating your second factor" : "验证您的第二项时出错", "Access through untrusted domain" : "通过不被信任的域名访问", "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." : "请联系你的管理员。如果你就是管理员,请参照 config.sample.php 中的示例编辑 config/config.php 中的 \"trusted_domains\" 设置。", + "Further information how to configure this can be found in the %1$sdocumentation%2$s." : "配置此项的详细内容请查阅 %1$s文档%2$s。", "App update required" : "必须的应用更新", + "%1$s will be updated to version %2$s" : "%1$s 将被升级至版本 %2$s", "These apps will be updated:" : "以下应用将被更新:", "These incompatible apps will be disabled:" : "下述不兼容的应用将被禁用:", "The theme %s has been disabled." : "%s 主题已被禁用.", @@ -322,7 +349,9 @@ OC.L10N.register( "For help, see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation</a>." : "获取更多帮助,请查看<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">文档</a>。", "I know that if I continue doing the update via web UI has the risk, that the request runs into a timeout and could cause data loss, but I have a backup and know how to restore my instance in case of a failure." : "我知道继续通过Web UI进行更新的风险,请求超时运行,并可能导致数据丢失,但我有一个备份,并知道如何恢复。", "Upgrade via web on my own risk" : "通过网络升级的风险", + "Maintenance mode" : "维护模式", "This %s instance is currently in maintenance mode, which may take a while." : "该实例 %s 当前处于维护模式, 这将花费一些时间.", + "This page will refresh itself when the instance is available again." : "当实力再次可用时,页面会自动刷新。", "Contact your system administrator if this message persists or appeared unexpectedly." : "如果这个消息一直存在或不停出现, 请联系你的系统管理员.", "Updated \"%s\" to %s" : "更新 \"%s\" 为 %s", "%s (3rdparty)" : "%s(第三方)", @@ -346,6 +375,9 @@ OC.L10N.register( "Error setting expiration date" : "设置过期日期时出错", "The public link will expire no later than {days} days after it is created" : "该共享链接将在创建后 {days} 天失效", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} 通过链接共享", + "{sharee} (group)" : "{sharee} (分组)", + "{sharee} (remote)" : "{sharee} (外部)", + "{sharee} (email)" : "{sharee} (邮件)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "通过输入用户或组,联合云ID或电子邮件地址与其他人共享。", "Share with other people by entering a user or group or a federated cloud ID." : "通过输入用户或组或联合云ID与其他人共享。", "Share with other people by entering a user or group or an email address." : "输入用户/组织或邮箱地址来共享给其他人.", @@ -376,6 +408,9 @@ OC.L10N.register( "Back to log in" : "返回登录", "You are about to grant %s access to your %s account." : "你将分配 %s 访问权限给你的 %s 账户。", "Depending on your configuration, this button could also work to trust the domain:" : "取决于配置,此按钮也可用作设置信任域名:", + "Copy URL" : "复制超链接", + "Enable" : "启用", + "{sharee} (conversation)" : "{sharee}(对话)", "Please log in before granting %s access to your %s account." : "请在登录之前授权 %s 访问你的 %s 账户。", "Further information how to configure this can be found in the %sdocumentation%s." : "更多配置信息可以查看 %s文档%s。" }, diff --git a/core/l10n/zh_CN.json b/core/l10n/zh_CN.json index f9406028c0c..0aa703b9dc4 100644 --- a/core/l10n/zh_CN.json +++ b/core/l10n/zh_CN.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "启用维护模式", "Turned off maintenance mode" : "关闭维护模式", "Maintenance mode is kept active" : "维护模式已启用", - "Waiting for cron to finish (checks again in 5 seconds) …" : "等待cron进程结束(5秒后重新检测) …", "Updating database schema" : "正在更新数据库结构", "Updated database" : "数据库已更新", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "检查数据库结构是否可以更新 (这可能需要很长的时间, 这取决于数据库大小)", @@ -102,8 +101,8 @@ "({count} selected)" : "(选择了 {count} 个)", "Error loading file exists template" : "加载文件存在性模板失败", "Pending" : "等待", - "Copy to {folder}" : "复制{文件夹}", - "Move to {folder}" : "移动{文件夹}", + "Copy to {folder}" : "复制到 {folder}", + "Move to {folder}" : "移动到 {folder}", "New in" : "新品", "View changelog" : "查看更新记录", "Very weak password" : "非常弱的密码", @@ -120,6 +119,9 @@ "The PHP module \"fileinfo\" is missing. It is strongly recommended to enable this module to get the best results with MIME type detection." : "未找到 PHP 的 \"fileinfo\" 模块。强烈推荐启用该模块,从而获得更好的 MIME 类型探测结果。", "{name} below version {version} is installed, for stability and performance reasons it is recommended to update to a newer {name} version." : "{name} 已安装 {version} 版本,出于稳定和性能的考虑,建议更新到 {name} 版本。", "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 noopener\" href=\"{docLink}\">documentation ↗</a> for more information." : "已禁用事务性文件锁定,这可能在竞争条件下导致问题。在 config.php 中启用 \"filelocking.enabled\" 可以避免此问题。详情查阅 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档 ↗</a>。", + "If your installation is not installed at 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 (suggestion: \"{suggestedOverwriteCliURL}\")" : "如果没有将 Nextcloud 安装到域名根目录并使用系统计划任务,生成超链接就会出现问题。为避免此问题,请在 config.php 配置文件中将 \"overwrite.cli.url\" 设置为你 Nextcloud 安装的路径。(建议:\"{suggestedOverwriteCliURL}\")", + "It was not possible to execute the cron job via CLI. The following technical errors have appeared:" : "无法通过 CLI 执行计划任务,请查看以下技术错误:", + "Last background job execution ran {relativeTime}. Something seems wrong." : "最近一次执行后台任务运行时间为 {relativeTime},似乎哪里出了问题。", "Check the background job settings" : "请检查后台任务设置", "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." : "此服务器没有可用的互联网连接:多个节点无法访问。这意味着某些功能比如挂载外部存储,更新通知以及安装第三方应用将无法工作。远程访问文件和发送通知邮件可能也不工作。启用这台服务器上的互联网连接以享用所有功能。", "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>." : "内存缓存未配置,为了提升使用体验,请尽量配置内存缓存。更多信息请参见<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档</a>。", @@ -128,22 +130,33 @@ "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "反向代理头部配置错误,或者您正在通过可信的代理访问 Nextcloud。如果您不是通过可信代理访问 Nextcloud,这是一个安全问题,它允许攻击者通过伪装 IP 地址访问 Nextcloud。更多信息请查看<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档</a>。", "Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached 当前配置为分布式缓存, 但是当前安装的 PHP 模块是 \"memcache\". \\OC\\Memcache\\Memcached 仅支持 \"memcached\" 而不是 \"memcache\". 点击 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{wikiLink}\">memcached wiki </a>了解两者的差别。", "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "一些文件没有通过完整性检查。了解如何解决该问题请查看我们的 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档</a>。(<a href=\"{codeIntegrityDownloadEndpoint}\">无效文件列表…</a> / <a href=\"{rescanEndpoint}\">重新扫描…</a>)", + "The PHP OPcache module is not loaded. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to load it into your PHP installation." : "PHP 的 OPcache 模块未载入。<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">推荐开启获得更好的性能</a>。", "The PHP OPcache is not properly configured. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to use the following settings in the <code>php.ini</code>:" : "PHP 的组件 OPcache 没有正确配置。 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">为了提供更好的性能</a>,我们建议在 <code>php.ini</code>中使用下列设置:", "The PHP function \"set_time_limit\" is not available. This could result in scripts being halted mid-execution, breaking your installation. Enabling this function is strongly recommended." : "PHP函数“set_time_limit”不可用。 这可能会导致脚本在执行过程中暂停,从而导致安装中断。 我们强烈建议启用此功能。", "Your PHP does not have FreeType support, resulting in breakage of profile pictures and the settings interface." : "您的 PHP 没有 FreeType 支持,导致配置文件图片和设置界面中断。", "Missing index \"{indexName}\" in table \"{tableName}\"." : "在数据表 \"{tableName}\" 中无法找到索引 \"{indexName}\" .", + "The database is missing some indexes. Due to the fact that adding indexes on big tables could take some time they were not added automatically. By running \"occ db:add-missing-indices\" those missing indexes could be added manually while the instance keeps running. Once the indexes are added queries to those tables are usually much faster." : "数据库丢失了一些索引。由于给大的数据表添加索引会耗费一些时间,因此程序没有自动对其进行修复。您可以在 Nextcloud 运行时通过命令行手动执行 \"occ db:add-missing-indices\" 命令修复丢失的索引。索引修复后会大大提高相应表的查询速度。", + "SQLite is currently being used as the backend database. For larger installations we recommend that you switch to a different database backend." : "当前正在使用 SQLite 作为后端数据库。多用户使用时,推荐您改用其他的数据库。", + "This is particularly recommended when using the desktop client for file synchronisation." : "特别推荐使用桌面客户端同步的用户选择。", + "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation ↗</a>." : "迁移到其他数据库,使用命令:'occ db:convert-type' 或查阅 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">文档↗</a>。", + "Use of the the built in php mailer is no longer supported. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">Please update your email server settings ↗<a/>." : "PHP 内建的邮件发送器已不再受支持。<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">请更新你的 E-mail 服务器设置↗<a/>。", "The PHP memory limit is below the recommended value of 512MB." : "PHP内存限制低于建议值512MB.", + "Some app directories are owned by a different user than the web server one. This may be the case if apps have been installed manually. Check the permissions of the following app directories:" : "有些应用程序目录是由与 Web 服务器不同的用户拥有的。如果应用程序是手动安装的,情况可能是这样的。检查以下应用程序目录的权限:", "Error occurred while checking server setup" : "检查服务器设置时出错", "Your data directory and files are probably accessible from the Internet. The .htaccess file is not working. It is strongly recommended that you configure your web server so that the data directory is no longer accessible, or move the data directory outside the web server document root." : "您的数据目录和文件可以从互联网直接访问。.htaccess 文件不起作用。强烈建议您配置 Web 服务器,以便数据目录不再可访问,或者你可以将数据目录移动到 Web 服务器文档根目录。", "The \"{header}\" HTTP header is not set to \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "HTTP 请求头 \"{header}\" 没有配置为 \"{expected}\"。这是一个潜在的安全或隐私风险, 我们建议您调整这项设置.", "The \"{header}\" HTTP header is not set to \"{expected}\". Some features might not work correctly, as it is recommended to adjust this setting accordingly." : "HTTP 请求头 \"{header}\" 没有配置为 \"{expected}\"。某些功能可能无法正常工作,因此建议相应地调整此设置。", + "The \"{header}\" HTTP header doesn't contain \"{expected}\". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly." : "HTTP 头 \"{header}\" 未包含 \"{expected}\"。这是一种潜在的安全或隐私风险,因此推荐调整此项设置。", + "The \"{header}\" HTTP header is not set to \"{val1}\", \"{val2}\", \"{val3}\", \"{val4}\" or \"{val5}\". This can leak referer information. See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C Recommendation ↗</a>." : "HTTP 头 \"{header}\" 未设置成 \"{val1}\",\"{val2}\",\"{val3}\",\"{val4}\" 或 \"{val5}\"。这会泄露更多的信息。请查阅 <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{link}\">W3C 建议↗</a>。", "The \"Strict-Transport-Security\" HTTP header is not set to at least \"{seconds}\" seconds. For enhanced security, it is recommended to enable HSTS as described in the <a href=\"{docUrl}\" rel=\"noreferrer noopener\">security tips ↗</a>." : "HTTP的请求头 \"Strict-Transport-Security\" 未设置为至少 \"{seconds}\" 秒. 为了提高安全性,建议参照<a href=\"{docUrl}\" rel=\"noreferrer noopener\">security tips ↗</a>中的说明启用HSTS.", + "Accessing site insecurely via HTTP. You are strongly adviced to set up your server to require HTTPS instead, as described in the <a href=\"{docUrl}\">security tips ↗</a>." : "通过 HTTP 访问网站不安全。强烈建议您将服务器设置成 HTTPS 协议,请查阅 <a href=\"{docUrl}\">安全贴士↗</a>。", "Shared" : "已共享", "Shared with" : "共享给", "Shared by" : "共享人", "Choose a password for the public link" : "为公开链接设置密码", "Choose a password for the public link or press the \"Enter\" key" : "为公开链接设置密码, 或按 \"回车\" 键", "Copied!" : "已经复制!", + "Copy link" : "复制链接", "Not supported!" : "无法支持!", "Press ⌘-C to copy." : "按 ⌘ + C 进行复制.", "Press Ctrl-C to copy." : "按 Ctrl + C 进行复制.", @@ -160,26 +173,30 @@ "Set expiration date" : "设置过期日期", "Expiration" : "过期", "Expiration date" : "过期日期", + "Note to recipient" : "备注", + "Unshare" : "取消共享", "Share link" : "共享链接", - "Enable" : "启用", + "Password protect by Talk" : "通过 Talk 保护密码", + "Could not unshare" : "无法共享", "Shared with you and the group {group} by {owner}" : "{owner} 共享给您及 {group} 分组", "Shared with you and {circle} by {owner}" : "{owner} 共享给您及 {circle}", "Shared with you and the conversation {conversation} by {owner}" : "{owner} 共享给您及对话 {conversation}", + "Shared with you in a conversation by {owner}" : "由 {owner} 通过一个对话与你分享", "Shared with you by {owner}" : "{owner} 共享给您", "Choose a password for the mail share" : "为电子邮件共享选择一个密码", "group" : "群组", "remote" : "外部", "remote group" : "远程群组", "email" : "邮件", + "conversation" : "对话", "shared by {sharer}" : "由 {sharer} 共享", - "Unshare" : "取消共享", "Can reshare" : "可以再次共享", "Can edit" : "可以编辑", "Can create" : "可以创建", "Can change" : "可以修改", "Can delete" : "可以删除", "Access control" : "访问控制", - "Could not unshare" : "无法共享", + "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} 通过链接共享", "Error while sharing" : "共享时出错", "Share details could not be loaded for this item." : "无法加载这个项目的共享详情.", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["{count}字符需要自动完成"], @@ -188,9 +205,7 @@ "No users found for {search}" : "没有找到 {search} 用户", "An error occurred (\"{message}\"). Please try again" : "发生错误 (\"{message}\"). 请重试", "An error occurred. Please try again" : "发生错误. 请重试", - "{sharee} (group)" : "{sharee} (分组)", - "{sharee} (remote)" : "{sharee} (外部)", - "{sharee} (email)" : "{sharee} (邮件)", + "{sharee} (remote group)" : "{sharee}(远程组)", "{sharee} ({type}, {owner})" : "{share}({type},{owner})", "Share" : "共享", "Name or email address..." : "姓名或电子邮件地址...", @@ -233,6 +248,8 @@ "Help" : "帮助", "Access forbidden" : "访问禁止", "File not found" : "文件未找到", + "The document could not be found on the server. Maybe the share was deleted or has expired?" : "服务器上找不到该文档。可能此共享已被删除或过期。", + "Back to %s" : "返回 %s", "Internal Server Error" : "内部服务器错误", "The server was unable to complete your request." : "服务器不能完成你的请求。", "If this happens again, please send the technical details below to the server administrator." : "如果再次发生,请在下方将技术详情发送给服务器管理员。", @@ -272,6 +289,8 @@ "Need help?" : "需要帮助?", "See the documentation" : "查看文档", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "对于正确的操作, 该应用需要使用 JavaScript. 请 {linkstart}启用 JavaScript{linkend}, 并重新加载页面.", + "Skip to main content" : "跳过主内容", + "Skip to navigation of app" : "跳过应用向导", "More apps" : "更多的应用程序", "More apps menu" : "更多的应用菜单", "Search" : "搜索", @@ -292,22 +311,30 @@ "Forgot password?" : "忘记密码?", "Back to login" : "返回登录", "Connect to your account" : "连接您的账户", + "Please log in before granting %1$s access to your %2$s account." : "在授权 %1$s 访问您的 %2$s 账户之前,请先登录。", "App token" : "App 令牌", "Grant access" : "授权访问", "Alternative log in using app token" : "使用应用程序令牌替代登录", "Account access" : "账户访问", + "You are about to grant %1$s access to your %2$s account." : "您正在授权 %1$s 访问您的 %2$s 账户。", "Redirecting …" : "正在跳转 …", "New password" : "新密码", "New Password" : "新密码", "This share is password-protected" : "这个共享是被密码保护的", "The password is wrong. Try again." : "密码错误.请重试.", "Two-factor authentication" : "双重认证", + "Enhanced security is enabled for your account. Choose a second factor for authentication:" : "您的账户已启用安全增强。请选择第二种验证方式。", + "Could not load at least one of your enabled two-factor auth methods. Please contact your admin." : "无法载入你启用的任何双因素验证方法。请联系管理员。", + "Two-factor authentication is enforced but has not been configured on your account. Contact your admin for assistance." : "双因素验证是强制性的,但你的账户似乎未做配置。请联系管理员获得支持。", + "Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance." : "双因素验证是强制性的,但你的账户似乎未做配置。使用你的备份代码登录或求助管理员。", "Use backup code" : "使用备用口令", "Cancel log in" : "取消登录", "Error while validating your second factor" : "验证您的第二项时出错", "Access through untrusted domain" : "通过不被信任的域名访问", "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." : "请联系你的管理员。如果你就是管理员,请参照 config.sample.php 中的示例编辑 config/config.php 中的 \"trusted_domains\" 设置。", + "Further information how to configure this can be found in the %1$sdocumentation%2$s." : "配置此项的详细内容请查阅 %1$s文档%2$s。", "App update required" : "必须的应用更新", + "%1$s will be updated to version %2$s" : "%1$s 将被升级至版本 %2$s", "These apps will be updated:" : "以下应用将被更新:", "These incompatible apps will be disabled:" : "下述不兼容的应用将被禁用:", "The theme %s has been disabled." : "%s 主题已被禁用.", @@ -320,7 +347,9 @@ "For help, see the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">documentation</a>." : "获取更多帮助,请查看<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"%s\">文档</a>。", "I know that if I continue doing the update via web UI has the risk, that the request runs into a timeout and could cause data loss, but I have a backup and know how to restore my instance in case of a failure." : "我知道继续通过Web UI进行更新的风险,请求超时运行,并可能导致数据丢失,但我有一个备份,并知道如何恢复。", "Upgrade via web on my own risk" : "通过网络升级的风险", + "Maintenance mode" : "维护模式", "This %s instance is currently in maintenance mode, which may take a while." : "该实例 %s 当前处于维护模式, 这将花费一些时间.", + "This page will refresh itself when the instance is available again." : "当实力再次可用时,页面会自动刷新。", "Contact your system administrator if this message persists or appeared unexpectedly." : "如果这个消息一直存在或不停出现, 请联系你的系统管理员.", "Updated \"%s\" to %s" : "更新 \"%s\" 为 %s", "%s (3rdparty)" : "%s(第三方)", @@ -344,6 +373,9 @@ "Error setting expiration date" : "设置过期日期时出错", "The public link will expire no later than {days} days after it is created" : "该共享链接将在创建后 {days} 天失效", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} 通过链接共享", + "{sharee} (group)" : "{sharee} (分组)", + "{sharee} (remote)" : "{sharee} (外部)", + "{sharee} (email)" : "{sharee} (邮件)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "通过输入用户或组,联合云ID或电子邮件地址与其他人共享。", "Share with other people by entering a user or group or a federated cloud ID." : "通过输入用户或组或联合云ID与其他人共享。", "Share with other people by entering a user or group or an email address." : "输入用户/组织或邮箱地址来共享给其他人.", @@ -374,6 +406,9 @@ "Back to log in" : "返回登录", "You are about to grant %s access to your %s account." : "你将分配 %s 访问权限给你的 %s 账户。", "Depending on your configuration, this button could also work to trust the domain:" : "取决于配置,此按钮也可用作设置信任域名:", + "Copy URL" : "复制超链接", + "Enable" : "启用", + "{sharee} (conversation)" : "{sharee}(对话)", "Please log in before granting %s access to your %s account." : "请在登录之前授权 %s 访问你的 %s 账户。", "Further information how to configure this can be found in the %sdocumentation%s." : "更多配置信息可以查看 %s文档%s。" },"pluralForm" :"nplurals=1; plural=0;" diff --git a/core/l10n/zh_TW.js b/core/l10n/zh_TW.js index db99f2107a3..98cd2a24a45 100644 --- a/core/l10n/zh_TW.js +++ b/core/l10n/zh_TW.js @@ -35,7 +35,6 @@ OC.L10N.register( "Turned on maintenance mode" : "已啓用維護模式", "Turned off maintenance mode" : "已停用維護模式", "Maintenance mode is kept active" : "維護模式維持在開啟狀態", - "Waiting for cron to finish (checks again in 5 seconds) …" : "等待 cron 結束(5 秒後重新檢查)…", "Updating database schema" : "更新資料庫格式", "Updated database" : "已更新資料庫", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "檢查是否有可更新的資料庫格式(若資料庫較大,可能需要一段時間)", @@ -143,12 +142,12 @@ OC.L10N.register( "Choose a password for the public link" : "為公開連結選一個密碼", "Choose a password for the public link or press the \"Enter\" key" : "為公開連結選一個密碼或是按下 Enter 鍵", "Copied!" : "已複製", + "Copy link" : "複製連結", "Not supported!" : "不支援!", "Press ⌘-C to copy." : "按下 ⌘-C 來複製", "Press Ctrl-C to copy." : "按下 Ctrl-C 來複製", "Resharing is not allowed" : "不允許重新分享", "Share to {name}" : "分享給 {name}", - "Copy link" : "複製連結", "Link" : "連結", "Password protect" : "密碼保護", "Allow editing" : "允許編輯", @@ -161,8 +160,10 @@ OC.L10N.register( "Expiration" : "過期", "Expiration date" : "到期日", "Note to recipient" : "給收件人的訊息", + "Unshare" : "取消分享", "Share link" : "分享連結", - "Enable" : "啟用", + "Password protect by Talk" : "密碼受 Talk 保護", + "Could not unshare" : "無法取消分享", "Shared with you and the group {group} by {owner}" : "由 {owner} 分享給您和 {group}", "Shared with you and {circle} by {owner}" : "{owner} 分享給你和 {circle}", "Shared with you and the conversation {conversation} by {owner}" : "{owner} 分享給你和 {conversation} 對話", @@ -175,16 +176,13 @@ OC.L10N.register( "email" : "email", "conversation" : "對話", "shared by {sharer}" : "由 {sharer} 分享", - "Unshare" : "取消分享", "Can reshare" : "允許轉分享", "Can edit" : "允許編輯", "Can create" : "新增", "Can change" : "允許更動", "Can delete" : "允許刪除", - "Password protect by Talk" : "密碼受 Talk 保護", "Access control" : "存取控制", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} 分享了連結", - "Could not unshare" : "無法取消分享", "Error while sharing" : "分享時發生錯誤", "Share details could not be loaded for this item." : "無法載入分享細節", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["至少需要 {count} 字才能自動完成"], @@ -193,12 +191,8 @@ OC.L10N.register( "No users found for {search}" : "沒有使用者符合 {search}", "An error occurred (\"{message}\"). Please try again" : "發生錯誤({message}),請再試一次", "An error occurred. Please try again" : "發生錯誤,請再試一次", - "{sharee} (group)" : "{sharee} (群組)", - "{sharee} (remote)" : "{sharee} (遠端)", "{sharee} (remote group)" : "{sharee} (遠端群組)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (對話)", "Share" : "分享", "Name or email address..." : "名字或電子郵件地址", "Name or federated cloud ID..." : "名稱或者聯盟式雲端ID...", @@ -353,6 +347,9 @@ OC.L10N.register( "Error setting expiration date" : "設定到期日發生錯誤", "The public link will expire no later than {days} days after it is created" : "這個公開連結會在 {days} 天內失效", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} 分享了連結", + "{sharee} (group)" : "{sharee} (群組)", + "{sharee} (remote)" : "{sharee} (遠端)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "透過輸入使用者、群組名稱,聯盟式雲端ID或e-mail信箱來分享給其他人。 ", "Share with other people by entering a user or group or a federated cloud ID." : "透過輸入使用者、群組名稱,聯盟式雲端ID來分享給其他人。", "Share with other people by entering a user or group or an email address." : "透過輸入使用者、群組名稱或email來分享給其他人。", @@ -379,6 +376,8 @@ OC.L10N.register( "Back to log in" : "回到登入頁面", "You are about to grant %s access to your %s account." : "您將授予「%s」存取您的 %s 帳戶", "Depending on your configuration, this button could also work to trust the domain:" : "根據你的設定值,此按鈕也可用於信任以下網域:", + "Enable" : "啟用", + "{sharee} (conversation)" : "{sharee} (對話)", "Please log in before granting %s access to your %s account." : "請登入後再授權 %s 存取你的 %s 帳號", "Further information how to configure this can be found in the %sdocumentation%s." : "關於如何設定這個的更多訊息,請見 %s 文件 %s" }, diff --git a/core/l10n/zh_TW.json b/core/l10n/zh_TW.json index 45c57f4bc38..c9ea8a54ef5 100644 --- a/core/l10n/zh_TW.json +++ b/core/l10n/zh_TW.json @@ -33,7 +33,6 @@ "Turned on maintenance mode" : "已啓用維護模式", "Turned off maintenance mode" : "已停用維護模式", "Maintenance mode is kept active" : "維護模式維持在開啟狀態", - "Waiting for cron to finish (checks again in 5 seconds) …" : "等待 cron 結束(5 秒後重新檢查)…", "Updating database schema" : "更新資料庫格式", "Updated database" : "已更新資料庫", "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "檢查是否有可更新的資料庫格式(若資料庫較大,可能需要一段時間)", @@ -141,12 +140,12 @@ "Choose a password for the public link" : "為公開連結選一個密碼", "Choose a password for the public link or press the \"Enter\" key" : "為公開連結選一個密碼或是按下 Enter 鍵", "Copied!" : "已複製", + "Copy link" : "複製連結", "Not supported!" : "不支援!", "Press ⌘-C to copy." : "按下 ⌘-C 來複製", "Press Ctrl-C to copy." : "按下 Ctrl-C 來複製", "Resharing is not allowed" : "不允許重新分享", "Share to {name}" : "分享給 {name}", - "Copy link" : "複製連結", "Link" : "連結", "Password protect" : "密碼保護", "Allow editing" : "允許編輯", @@ -159,8 +158,10 @@ "Expiration" : "過期", "Expiration date" : "到期日", "Note to recipient" : "給收件人的訊息", + "Unshare" : "取消分享", "Share link" : "分享連結", - "Enable" : "啟用", + "Password protect by Talk" : "密碼受 Talk 保護", + "Could not unshare" : "無法取消分享", "Shared with you and the group {group} by {owner}" : "由 {owner} 分享給您和 {group}", "Shared with you and {circle} by {owner}" : "{owner} 分享給你和 {circle}", "Shared with you and the conversation {conversation} by {owner}" : "{owner} 分享給你和 {conversation} 對話", @@ -173,16 +174,13 @@ "email" : "email", "conversation" : "對話", "shared by {sharer}" : "由 {sharer} 分享", - "Unshare" : "取消分享", "Can reshare" : "允許轉分享", "Can edit" : "允許編輯", "Can create" : "新增", "Can change" : "允許更動", "Can delete" : "允許刪除", - "Password protect by Talk" : "密碼受 Talk 保護", "Access control" : "存取控制", "{shareInitiatorDisplayName} shared via link" : "{shareInitiatorDisplayName} 分享了連結", - "Could not unshare" : "無法取消分享", "Error while sharing" : "分享時發生錯誤", "Share details could not be loaded for this item." : "無法載入分享細節", "_At least {count} character is needed for autocompletion_::_At least {count} characters are needed for autocompletion_" : ["至少需要 {count} 字才能自動完成"], @@ -191,12 +189,8 @@ "No users found for {search}" : "沒有使用者符合 {search}", "An error occurred (\"{message}\"). Please try again" : "發生錯誤({message}),請再試一次", "An error occurred. Please try again" : "發生錯誤,請再試一次", - "{sharee} (group)" : "{sharee} (群組)", - "{sharee} (remote)" : "{sharee} (遠端)", "{sharee} (remote group)" : "{sharee} (遠端群組)", - "{sharee} (email)" : "{sharee} (email)", "{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})", - "{sharee} (conversation)" : "{sharee} (對話)", "Share" : "分享", "Name or email address..." : "名字或電子郵件地址", "Name or federated cloud ID..." : "名稱或者聯盟式雲端ID...", @@ -351,6 +345,9 @@ "Error setting expiration date" : "設定到期日發生錯誤", "The public link will expire no later than {days} days after it is created" : "這個公開連結會在 {days} 天內失效", "{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} 分享了連結", + "{sharee} (group)" : "{sharee} (群組)", + "{sharee} (remote)" : "{sharee} (遠端)", + "{sharee} (email)" : "{sharee} (email)", "Share with other people by entering a user or group, a federated cloud ID or an email address." : "透過輸入使用者、群組名稱,聯盟式雲端ID或e-mail信箱來分享給其他人。 ", "Share with other people by entering a user or group or a federated cloud ID." : "透過輸入使用者、群組名稱,聯盟式雲端ID來分享給其他人。", "Share with other people by entering a user or group or an email address." : "透過輸入使用者、群組名稱或email來分享給其他人。", @@ -377,6 +374,8 @@ "Back to log in" : "回到登入頁面", "You are about to grant %s access to your %s account." : "您將授予「%s」存取您的 %s 帳戶", "Depending on your configuration, this button could also work to trust the domain:" : "根據你的設定值,此按鈕也可用於信任以下網域:", + "Enable" : "啟用", + "{sharee} (conversation)" : "{sharee} (對話)", "Please log in before granting %s access to your %s account." : "請登入後再授權 %s 存取你的 %s 帳號", "Further information how to configure this can be found in the %sdocumentation%s." : "關於如何設定這個的更多訊息,請見 %s 文件 %s" },"pluralForm" :"nplurals=1; plural=0;" diff --git a/core/register_command.php b/core/register_command.php index af8d9977c7f..fb029f1be4a 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -65,6 +65,8 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $application->add(new OC\Core\Command\App\Install()); $application->add(new OC\Core\Command\App\GetPath()); $application->add(new OC\Core\Command\App\ListApps(\OC::$server->getAppManager())); + $application->add(new OC\Core\Command\App\Remove(\OC::$server->getAppManager(), \OC::$server->query(\OC\Installer::class), \OC::$server->getLogger())); + $application->add(\OC::$server->query(\OC\Core\Command\App\Update::class)); $application->add(\OC::$server->query(\OC\Core\Command\TwoFactorAuth\Cleanup::class)); $application->add(\OC::$server->query(\OC\Core\Command\TwoFactorAuth\Enforce::class)); diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index d82043b2572..6f0344aa600 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -47,7 +47,7 @@ <ul id="appmenu" <?php if ($_['themingInvertMenu']) { ?>class="inverted"<?php } ?>> <?php foreach ($_['navigation'] as $entry): ?> - <li data-id="<?php p($entry['id']); ?>" class="hidden"> + <li data-id="<?php p($entry['id']); ?>" class="hidden" tabindex="-1"> <a href="<?php print_unescaped($entry['href']); ?>" <?php if ($entry['active']): ?> class="active"<?php endif; ?> aria-label="<?php p($entry['name']); ?>"> @@ -69,7 +69,7 @@ aria-haspopup="true" aria-controls="navigation" aria-expanded="false"> <a href="#" aria-label="<?php p($l->t('More apps')); ?>"> <div class="icon-more-white"></div> - <span><?php p($l->t('More apps')); ?></span> + <span><?php p($l->t('More')); ?></span> </a> </li> </ul> diff --git a/core/templates/login.php b/core/templates/login.php index 989ea1eaad5..3035d23da70 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -42,7 +42,7 @@ use OC\Core\Controller\LoginController; aria-label="<?php p($l->t('Username or email')); ?>" value="<?php p($_['loginName']); ?>" <?php p($_['user_autofocus'] ? 'autofocus' : ''); ?> - autocomplete="on" autocapitalize="none" autocorrect="off" required> + autocomplete="<?php p($_['login_form_autocomplete']); ?>" autocapitalize="none" autocorrect="off" required> <label for="user" class="infield"><?php p($l->t('Username or email')); ?></label> </p> @@ -51,7 +51,7 @@ use OC\Core\Controller\LoginController; placeholder="<?php p($l->t('Password')); ?>" aria-label="<?php p($l->t('Password')); ?>" <?php p($_['user_autofocus'] ? '' : 'autofocus'); ?> - autocomplete="on" autocapitalize="off" autocorrect="none" required> + autocomplete="<?php p($_['login_form_autocomplete']); ?>" autocapitalize="none" autocorrect="off" required> <label for="password" class="infield"><?php p($l->t('Password')); ?></label> </p> diff --git a/index.php b/index.php index ba83054ccca..7eabe64c160 100644 --- a/index.php +++ b/index.php @@ -78,7 +78,7 @@ try { print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n"); print("More details can be found in the webserver log.\n"); - throw $e; + throw $ex; } OC_Template::printExceptionErrorPage($ex, 500); } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 863d0e62837..6c2463939bd 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -231,7 +231,25 @@ return array( 'OCP\\Files\\Storage\\INotifyStorage' => $baseDir . '/lib/public/Files/Storage/INotifyStorage.php', 'OCP\\Files\\Storage\\IStorage' => $baseDir . '/lib/public/Files/Storage/IStorage.php', 'OCP\\Files\\Storage\\IStorageFactory' => $baseDir . '/lib/public/Files/Storage/IStorageFactory.php', + 'OCP\\Files\\Storage\\IWriteStreamStorage' => $baseDir . '/lib/public/Files/Storage/IWriteStreamStorage.php', 'OCP\\Files\\UnseekableException' => $baseDir . '/lib/public/Files/UnseekableException.php', + 'OCP\\Files_FullTextSearch\\Model\\AFilesDocument' => $baseDir . '/lib/public/Files_FullTextSearch/Model/AFilesDocument.php', + 'OCP\\FullTextSearch\\Exceptions\\FullTextSearchAppNotAvailableException' => $baseDir . '/lib/public/FullTextSearch/Exceptions/FullTextSearchAppNotAvailableException.php', + 'OCP\\FullTextSearch\\IFullTextSearchManager' => $baseDir . '/lib/public/FullTextSearch/IFullTextSearchManager.php', + 'OCP\\FullTextSearch\\IFullTextSearchPlatform' => $baseDir . '/lib/public/FullTextSearch/IFullTextSearchPlatform.php', + 'OCP\\FullTextSearch\\IFullTextSearchProvider' => $baseDir . '/lib/public/FullTextSearch/IFullTextSearchProvider.php', + 'OCP\\FullTextSearch\\Model\\DocumentAccess' => $baseDir . '/lib/public/FullTextSearch/Model/DocumentAccess.php', + 'OCP\\FullTextSearch\\Model\\IIndex' => $baseDir . '/lib/public/FullTextSearch/Model/IIndex.php', + 'OCP\\FullTextSearch\\Model\\IIndexOptions' => $baseDir . '/lib/public/FullTextSearch/Model/IIndexOptions.php', + 'OCP\\FullTextSearch\\Model\\IRunner' => $baseDir . '/lib/public/FullTextSearch/Model/IRunner.php', + 'OCP\\FullTextSearch\\Model\\ISearchRequest' => $baseDir . '/lib/public/FullTextSearch/Model/ISearchRequest.php', + 'OCP\\FullTextSearch\\Model\\ISearchResult' => $baseDir . '/lib/public/FullTextSearch/Model/ISearchResult.php', + 'OCP\\FullTextSearch\\Model\\IndexDocument' => $baseDir . '/lib/public/FullTextSearch/Model/IndexDocument.php', + 'OCP\\FullTextSearch\\Model\\SearchOption' => $baseDir . '/lib/public/FullTextSearch/Model/SearchOption.php', + 'OCP\\FullTextSearch\\Model\\SearchTemplate' => $baseDir . '/lib/public/FullTextSearch/Model/SearchTemplate.php', + 'OCP\\FullTextSearch\\Service\\IIndexService' => $baseDir . '/lib/public/FullTextSearch/Service/IIndexService.php', + 'OCP\\FullTextSearch\\Service\\IProviderService' => $baseDir . '/lib/public/FullTextSearch/Service/IProviderService.php', + 'OCP\\FullTextSearch\\Service\\ISearchService' => $baseDir . '/lib/public/FullTextSearch/Service/ISearchService.php', 'OCP\\GlobalScale\\IConfig' => $baseDir . '/lib/public/GlobalScale/IConfig.php', 'OCP\\GroupInterface' => $baseDir . '/lib/public/GroupInterface.php', 'OCP\\Group\\Backend\\ABackend' => $baseDir . '/lib/public/Group/Backend/ABackend.php', @@ -458,6 +476,7 @@ return array( 'OC\\Archive\\Archive' => $baseDir . '/lib/private/Archive/Archive.php', 'OC\\Archive\\TAR' => $baseDir . '/lib/private/Archive/TAR.php', 'OC\\Archive\\ZIP' => $baseDir . '/lib/private/Archive/ZIP.php', + 'OC\\Authentication\\Exceptions\\ExpiredTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/ExpiredTokenException.php', 'OC\\Authentication\\Exceptions\\InvalidProviderException' => $baseDir . '/lib/private/Authentication/Exceptions/InvalidProviderException.php', 'OC\\Authentication\\Exceptions\\InvalidTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/InvalidTokenException.php', 'OC\\Authentication\\Exceptions\\LoginRequiredException' => $baseDir . '/lib/private/Authentication/Exceptions/LoginRequiredException.php', @@ -471,7 +490,6 @@ return array( 'OC\\Authentication\\Token\\DefaultTokenCleanupJob' => $baseDir . '/lib/private/Authentication/Token/DefaultTokenCleanupJob.php', 'OC\\Authentication\\Token\\DefaultTokenMapper' => $baseDir . '/lib/private/Authentication/Token/DefaultTokenMapper.php', 'OC\\Authentication\\Token\\DefaultTokenProvider' => $baseDir . '/lib/private/Authentication/Token/DefaultTokenProvider.php', - 'OC\\Authentication\\Token\\ExpiredTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/ExpiredTokenException.php', 'OC\\Authentication\\Token\\IProvider' => $baseDir . '/lib/private/Authentication/Token/IProvider.php', 'OC\\Authentication\\Token\\IToken' => $baseDir . '/lib/private/Authentication/Token/IToken.php', 'OC\\Authentication\\Token\\Manager' => $baseDir . '/lib/private/Authentication/Token/Manager.php', @@ -539,6 +557,8 @@ return array( 'OC\\Core\\Command\\App\\GetPath' => $baseDir . '/core/Command/App/GetPath.php', 'OC\\Core\\Command\\App\\Install' => $baseDir . '/core/Command/App/Install.php', 'OC\\Core\\Command\\App\\ListApps' => $baseDir . '/core/Command/App/ListApps.php', + 'OC\\Core\\Command\\App\\Remove' => $baseDir . '/core/Command/App/Remove.php', + 'OC\\Core\\Command\\App\\Update' => $baseDir . '/core/Command/App/Update.php', 'OC\\Core\\Command\\Background\\Ajax' => $baseDir . '/core/Command/Background/Ajax.php', 'OC\\Core\\Command\\Background\\Base' => $baseDir . '/core/Command/Background/Base.php', 'OC\\Core\\Command\\Background\\Cron' => $baseDir . '/core/Command/Background/Cron.php', @@ -651,6 +671,8 @@ return array( 'OC\\Core\\Migrations\\Version14000Date20180710092004' => $baseDir . '/core/Migrations/Version14000Date20180710092004.php', 'OC\\Core\\Migrations\\Version14000Date20180712153140' => $baseDir . '/core/Migrations/Version14000Date20180712153140.php', 'OC\\Core\\Migrations\\Version15000Date20180926101451' => $baseDir . '/core/Migrations/Version15000Date20180926101451.php', + 'OC\\Core\\Migrations\\Version15000Date20181015062942' => $baseDir . '/core/Migrations/Version15000Date20181015062942.php', + 'OC\\Core\\Migrations\\Version15000Date20181029084625' => $baseDir . '/core/Migrations/Version15000Date20181029084625.php', 'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php', 'OC\\DB\\AdapterMySQL' => $baseDir . '/lib/private/DB/AdapterMySQL.php', 'OC\\DB\\AdapterOCI8' => $baseDir . '/lib/private/DB/AdapterOCI8.php', @@ -802,6 +824,7 @@ return array( 'OC\\Files\\Storage\\Wrapper\\PermissionsMask' => $baseDir . '/lib/private/Files/Storage/Wrapper/PermissionsMask.php', 'OC\\Files\\Storage\\Wrapper\\Quota' => $baseDir . '/lib/private/Files/Storage/Wrapper/Quota.php', 'OC\\Files\\Storage\\Wrapper\\Wrapper' => $baseDir . '/lib/private/Files/Storage/Wrapper/Wrapper.php', + 'OC\\Files\\Stream\\CountReadStream' => $baseDir . '/lib/private/Files/Stream/CountReadStream.php', 'OC\\Files\\Stream\\Encryption' => $baseDir . '/lib/private/Files/Stream/Encryption.php', 'OC\\Files\\Stream\\Quota' => $baseDir . '/lib/private/Files/Stream/Quota.php', 'OC\\Files\\Type\\Detection' => $baseDir . '/lib/private/Files/Type/Detection.php', @@ -810,6 +833,7 @@ return array( 'OC\\Files\\Utils\\Scanner' => $baseDir . '/lib/private/Files/Utils/Scanner.php', 'OC\\Files\\View' => $baseDir . '/lib/private/Files/View.php', 'OC\\ForbiddenException' => $baseDir . '/lib/private/ForbiddenException.php', + 'OC\\FullTextSearch\\FullTextSearchManager' => $baseDir . '/lib/private/FullTextSearch/FullTextSearchManager.php', 'OC\\GlobalScale\\Config' => $baseDir . '/lib/private/GlobalScale/Config.php', 'OC\\Group\\Backend' => $baseDir . '/lib/private/Group/Backend.php', 'OC\\Group\\Database' => $baseDir . '/lib/private/Group/Database.php', @@ -942,6 +966,7 @@ return array( 'OC\\Repair\\NC13\\RepairInvalidPaths' => $baseDir . '/lib/private/Repair/NC13/RepairInvalidPaths.php', 'OC\\Repair\\NC14\\AddPreviewBackgroundCleanupJob' => $baseDir . '/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php', 'OC\\Repair\\NC14\\RepairPendingCronJobs' => $baseDir . '/lib/private/Repair/NC14/RepairPendingCronJobs.php', + 'OC\\Repair\\NC15\\SetVcardDatabaseUID' => $baseDir . '/lib/private/Repair/NC15/SetVcardDatabaseUID.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Owncloud\\DropAccountTermsTable' => $baseDir . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php', 'OC\\Repair\\Owncloud\\SaveAccountsTableData' => $baseDir . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index b14376045ab..847ae43fb65 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -261,7 +261,25 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Files\\Storage\\INotifyStorage' => __DIR__ . '/../../..' . '/lib/public/Files/Storage/INotifyStorage.php', 'OCP\\Files\\Storage\\IStorage' => __DIR__ . '/../../..' . '/lib/public/Files/Storage/IStorage.php', 'OCP\\Files\\Storage\\IStorageFactory' => __DIR__ . '/../../..' . '/lib/public/Files/Storage/IStorageFactory.php', + 'OCP\\Files\\Storage\\IWriteStreamStorage' => __DIR__ . '/../../..' . '/lib/public/Files/Storage/IWriteStreamStorage.php', 'OCP\\Files\\UnseekableException' => __DIR__ . '/../../..' . '/lib/public/Files/UnseekableException.php', + 'OCP\\Files_FullTextSearch\\Model\\AFilesDocument' => __DIR__ . '/../../..' . '/lib/public/Files_FullTextSearch/Model/AFilesDocument.php', + 'OCP\\FullTextSearch\\Exceptions\\FullTextSearchAppNotAvailableException' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Exceptions/FullTextSearchAppNotAvailableException.php', + 'OCP\\FullTextSearch\\IFullTextSearchManager' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/IFullTextSearchManager.php', + 'OCP\\FullTextSearch\\IFullTextSearchPlatform' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/IFullTextSearchPlatform.php', + 'OCP\\FullTextSearch\\IFullTextSearchProvider' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/IFullTextSearchProvider.php', + 'OCP\\FullTextSearch\\Model\\DocumentAccess' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/DocumentAccess.php', + 'OCP\\FullTextSearch\\Model\\IIndex' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/IIndex.php', + 'OCP\\FullTextSearch\\Model\\IIndexOptions' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/IIndexOptions.php', + 'OCP\\FullTextSearch\\Model\\IRunner' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/IRunner.php', + 'OCP\\FullTextSearch\\Model\\ISearchRequest' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/ISearchRequest.php', + 'OCP\\FullTextSearch\\Model\\ISearchResult' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/ISearchResult.php', + 'OCP\\FullTextSearch\\Model\\IndexDocument' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/IndexDocument.php', + 'OCP\\FullTextSearch\\Model\\SearchOption' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/SearchOption.php', + 'OCP\\FullTextSearch\\Model\\SearchTemplate' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Model/SearchTemplate.php', + 'OCP\\FullTextSearch\\Service\\IIndexService' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Service/IIndexService.php', + 'OCP\\FullTextSearch\\Service\\IProviderService' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Service/IProviderService.php', + 'OCP\\FullTextSearch\\Service\\ISearchService' => __DIR__ . '/../../..' . '/lib/public/FullTextSearch/Service/ISearchService.php', 'OCP\\GlobalScale\\IConfig' => __DIR__ . '/../../..' . '/lib/public/GlobalScale/IConfig.php', 'OCP\\GroupInterface' => __DIR__ . '/../../..' . '/lib/public/GroupInterface.php', 'OCP\\Group\\Backend\\ABackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ABackend.php', @@ -488,6 +506,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Archive\\Archive' => __DIR__ . '/../../..' . '/lib/private/Archive/Archive.php', 'OC\\Archive\\TAR' => __DIR__ . '/../../..' . '/lib/private/Archive/TAR.php', 'OC\\Archive\\ZIP' => __DIR__ . '/../../..' . '/lib/private/Archive/ZIP.php', + 'OC\\Authentication\\Exceptions\\ExpiredTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/ExpiredTokenException.php', 'OC\\Authentication\\Exceptions\\InvalidProviderException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/InvalidProviderException.php', 'OC\\Authentication\\Exceptions\\InvalidTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/InvalidTokenException.php', 'OC\\Authentication\\Exceptions\\LoginRequiredException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/LoginRequiredException.php', @@ -501,7 +520,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Authentication\\Token\\DefaultTokenCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/DefaultTokenCleanupJob.php', 'OC\\Authentication\\Token\\DefaultTokenMapper' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/DefaultTokenMapper.php', 'OC\\Authentication\\Token\\DefaultTokenProvider' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/DefaultTokenProvider.php', - 'OC\\Authentication\\Token\\ExpiredTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/ExpiredTokenException.php', 'OC\\Authentication\\Token\\IProvider' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/IProvider.php', 'OC\\Authentication\\Token\\IToken' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/IToken.php', 'OC\\Authentication\\Token\\Manager' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/Manager.php', @@ -569,6 +587,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Command\\App\\GetPath' => __DIR__ . '/../../..' . '/core/Command/App/GetPath.php', 'OC\\Core\\Command\\App\\Install' => __DIR__ . '/../../..' . '/core/Command/App/Install.php', 'OC\\Core\\Command\\App\\ListApps' => __DIR__ . '/../../..' . '/core/Command/App/ListApps.php', + 'OC\\Core\\Command\\App\\Remove' => __DIR__ . '/../../..' . '/core/Command/App/Remove.php', + 'OC\\Core\\Command\\App\\Update' => __DIR__ . '/../../..' . '/core/Command/App/Update.php', 'OC\\Core\\Command\\Background\\Ajax' => __DIR__ . '/../../..' . '/core/Command/Background/Ajax.php', 'OC\\Core\\Command\\Background\\Base' => __DIR__ . '/../../..' . '/core/Command/Background/Base.php', 'OC\\Core\\Command\\Background\\Cron' => __DIR__ . '/../../..' . '/core/Command/Background/Cron.php', @@ -681,6 +701,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Migrations\\Version14000Date20180710092004' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180710092004.php', 'OC\\Core\\Migrations\\Version14000Date20180712153140' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180712153140.php', 'OC\\Core\\Migrations\\Version15000Date20180926101451' => __DIR__ . '/../../..' . '/core/Migrations/Version15000Date20180926101451.php', + 'OC\\Core\\Migrations\\Version15000Date20181015062942' => __DIR__ . '/../../..' . '/core/Migrations/Version15000Date20181015062942.php', + 'OC\\Core\\Migrations\\Version15000Date20181029084625' => __DIR__ . '/../../..' . '/core/Migrations/Version15000Date20181029084625.php', 'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php', 'OC\\DB\\AdapterMySQL' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterMySQL.php', 'OC\\DB\\AdapterOCI8' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterOCI8.php', @@ -832,6 +854,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Files\\Storage\\Wrapper\\PermissionsMask' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/PermissionsMask.php', 'OC\\Files\\Storage\\Wrapper\\Quota' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/Quota.php', 'OC\\Files\\Storage\\Wrapper\\Wrapper' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/Wrapper.php', + 'OC\\Files\\Stream\\CountReadStream' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/CountReadStream.php', 'OC\\Files\\Stream\\Encryption' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Encryption.php', 'OC\\Files\\Stream\\Quota' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Quota.php', 'OC\\Files\\Type\\Detection' => __DIR__ . '/../../..' . '/lib/private/Files/Type/Detection.php', @@ -840,6 +863,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Files\\Utils\\Scanner' => __DIR__ . '/../../..' . '/lib/private/Files/Utils/Scanner.php', 'OC\\Files\\View' => __DIR__ . '/../../..' . '/lib/private/Files/View.php', 'OC\\ForbiddenException' => __DIR__ . '/../../..' . '/lib/private/ForbiddenException.php', + 'OC\\FullTextSearch\\FullTextSearchManager' => __DIR__ . '/../../..' . '/lib/private/FullTextSearch/FullTextSearchManager.php', 'OC\\GlobalScale\\Config' => __DIR__ . '/../../..' . '/lib/private/GlobalScale/Config.php', 'OC\\Group\\Backend' => __DIR__ . '/../../..' . '/lib/private/Group/Backend.php', 'OC\\Group\\Database' => __DIR__ . '/../../..' . '/lib/private/Group/Database.php', @@ -972,6 +996,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\NC13\\RepairInvalidPaths' => __DIR__ . '/../../..' . '/lib/private/Repair/NC13/RepairInvalidPaths.php', 'OC\\Repair\\NC14\\AddPreviewBackgroundCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php', 'OC\\Repair\\NC14\\RepairPendingCronJobs' => __DIR__ . '/../../..' . '/lib/private/Repair/NC14/RepairPendingCronJobs.php', + 'OC\\Repair\\NC15\\SetVcardDatabaseUID' => __DIR__ . '/../../..' . '/lib/private/Repair/NC15/SetVcardDatabaseUID.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Owncloud\\DropAccountTermsTable' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php', 'OC\\Repair\\Owncloud\\SaveAccountsTableData' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php', diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 0485d178b49..2c745973ed2 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -320,14 +320,18 @@ class Request implements \ArrayAccess, \Countable, IRequest { // There's a few headers that seem to end up in the top-level // server array. - switch($name) { + switch ($name) { case 'CONTENT_TYPE' : case 'CONTENT_LENGTH' : if (isset($this->server[$name])) { return $this->server[$name]; } break; - + case 'REMOTE_ADDR' : + if (isset($this->server[$name])) { + return $this->server[$name]; + } + break; } return ''; @@ -595,6 +599,44 @@ class Request implements \ArrayAccess, \Countable, IRequest { } /** + * Checks if given $remoteAddress matches given $trustedProxy. + * If $trustedProxy is an IPv4 IP range given in CIDR notation, true will be returned if + * $remoteAddress is an IPv4 address within that IP range. + * Otherwise $remoteAddress will be compared to $trustedProxy literally and the result + * will be returned. + * @return boolean true if $remoteAddress matches $trustedProxy, false otherwise + */ + protected function matchesTrustedProxy($trustedProxy, $remoteAddress) { + $cidrre = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2})$/'; + + if (preg_match($cidrre, $trustedProxy, $match)) { + $net = $match[1]; + $shiftbits = min(32, max(0, 32 - intval($match[2]))); + $netnum = ip2long($net) >> $shiftbits; + $ipnum = ip2long($remoteAddress) >> $shiftbits; + + return $ipnum === $netnum; + } + + return $trustedProxy === $remoteAddress; + } + + /** + * Checks if given $remoteAddress matches any entry in the given array $trustedProxies. + * For details regarding what "match" means, refer to `matchesTrustedProxy`. + * @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise + */ + protected function isTrustedProxy($trustedProxies, $remoteAddress) { + foreach ($trustedProxies as $tp) { + if ($this->matchesTrustedProxy($tp, $remoteAddress)) { + return true; + } + } + + return false; + } + + /** * Returns the remote address, if the connection came from a trusted proxy * and `forwarded_for_headers` has been configured then the IP address * specified in this header will be returned instead. @@ -605,7 +647,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { $remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : ''; $trustedProxies = $this->config->getSystemValue('trusted_proxies', []); - if(\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies)) { + if(\is_array($trustedProxies) && $this->isTrustedProxy($trustedProxies, $remoteAddress)) { $forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [ 'HTTP_X_FORWARDED_FOR' // only have one default, so we cannot ship an insecure product out of the box diff --git a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php index 463e7cd93c9..7c1c4595e9a 100644 --- a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php @@ -39,6 +39,8 @@ class PasswordConfirmationMiddleware extends Middleware { private $userSession; /** @var ITimeFactory */ private $timeFactory; + /** @var array */ + private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true]; /** * PasswordConfirmationMiddleware constructor. @@ -73,7 +75,7 @@ class PasswordConfirmationMiddleware extends Middleware { $lastConfirm = (int) $this->session->get('last-password-confirm'); // we can't check the password against a SAML backend, so skip password confirmation in this case - if ($backendClassName !== 'user_saml' && $lastConfirm < ($this->timeFactory->getTime() - (30 * 60 + 15))) { // allow 15 seconds delay + if (!isset($this->excludedUserBackEnds[$backendClassName]) && $lastConfirm < ($this->timeFactory->getTime() - (30 * 60 + 15))) { // allow 15 seconds delay throw new NotConfirmedException(); } } diff --git a/lib/private/Authentication/Exceptions/ExpiredTokenException.php b/lib/private/Authentication/Exceptions/ExpiredTokenException.php index a45ca5b6955..d5b2e2cbca7 100644 --- a/lib/private/Authentication/Exceptions/ExpiredTokenException.php +++ b/lib/private/Authentication/Exceptions/ExpiredTokenException.php @@ -21,9 +21,9 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ -namespace OC\Authentication\Token; +namespace OC\Authentication\Exceptions; -use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Token\IToken; class ExpiredTokenException extends InvalidTokenException { /** @var IToken */ diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php index a27a875a27f..98609a3f14b 100644 --- a/lib/private/Authentication/Token/DefaultTokenProvider.php +++ b/lib/private/Authentication/Token/DefaultTokenProvider.php @@ -29,6 +29,7 @@ declare(strict_types=1); namespace OC\Authentication\Token; use Exception; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; use OCP\AppFramework\Db\DoesNotExistException; diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php index 7ee76b7b384..21223cecdf7 100644 --- a/lib/private/Authentication/Token/IProvider.php +++ b/lib/private/Authentication/Token/IProvider.php @@ -26,6 +26,7 @@ declare(strict_types=1); namespace OC\Authentication\Token; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; diff --git a/lib/private/Authentication/Token/Manager.php b/lib/private/Authentication/Token/Manager.php index 98a48f41523..3174599221d 100644 --- a/lib/private/Authentication/Token/Manager.php +++ b/lib/private/Authentication/Token/Manager.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace OC\Authentication\Token; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php index 33c0b1d59eb..9f596ac4568 100644 --- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php +++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace OC\Authentication\Token; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; use OCP\AppFramework\Db\DoesNotExistException; diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php index fab608cf164..e890c35868b 100644 --- a/lib/private/BackgroundJob/JobList.php +++ b/lib/private/BackgroundJob/JobList.php @@ -48,9 +48,6 @@ class JobList implements IJobList { /**@var ITimeFactory */ protected $timeFactory; - /** @var int - 12 hours * 3600 seconds*/ - private $jobTimeOut = 43200; - /** * @param IDBConnection $connection * @param IConfig $config @@ -186,7 +183,7 @@ class JobList implements IJobList { $query = $this->connection->getQueryBuilder(); $query->select('*') ->from('jobs') - ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT))) + ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 12 * 3600, IQueryBuilder::PARAM_INT))) ->andWhere($query->expr()->lte('last_checked', $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT))) ->orderBy('last_checked', 'ASC') ->setMaxResults(1); @@ -346,39 +343,4 @@ class JobList implements IJobList { ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT))); $query->execute(); } - - /** - * checks if a job is still running (reserved_at time is smaller than 12 hours ago) - * - * Background information: - * - * The 12 hours is the same timeout that is also used to re-schedule an non-terminated - * job (see getNext()). The idea here is to give a job enough time to run very - * long but still be able to recognize that it maybe crashed and re-schedule it - * after the timeout. It's more likely to be crashed at that time than it ran - * that long. - * - * In theory it could lead to an nearly endless loop (as in - at most 12 hours). - * The cron command will not start new jobs when maintenance mode is active and - * this method is only executed in maintenance mode (see where it is called in - * the upgrader class. So this means in the worst case we wait 12 hours when a - * job has crashed. On the other hand: then the instance should be fixed anyways. - * - * @return bool - */ - public function isAnyJobRunning(): bool { - $query = $this->connection->getQueryBuilder(); - $query->select('*') - ->from('jobs') - ->where($query->expr()->gt('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT))) - ->setMaxResults(1); - $result = $query->execute(); - $row = $result->fetch(); - $result->closeCursor(); - - if ($row) { - return true; - } - return false; - } } diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 101d6845ec3..6faa5d5d125 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -84,11 +84,17 @@ class MailPlugin implements ISearchPlugin { foreach ($addressBookContacts as $contact) { if (isset($contact['EMAIL'])) { $emailAddresses = $contact['EMAIL']; - if (!is_array($emailAddresses)) { + if (\is_string($emailAddresses)) { $emailAddresses = [$emailAddresses]; } - foreach ($emailAddresses as $emailAddress) { + foreach ($emailAddresses as $type => $emailAddress) { $displayName = $emailAddress; + $emailAddressType = null; + if (\is_array($emailAddress)) { + $emailAddressData = $emailAddress; + $emailAddress = $emailAddressData['value']; + $emailAddressType = $emailAddressData['type']; + } if (isset($contact['FN'])) { $displayName = $contact['FN'] . ' (' . $emailAddress . ')'; } @@ -121,6 +127,8 @@ class MailPlugin implements ISearchPlugin { if (!$this->isCurrentUser($cloud) && !$searchResult->hasResult($userType, $cloud->getUser())) { $singleResult = [[ 'label' => $displayName, + 'uuid' => $contact['UID'], + 'name' => $contact['FN'], 'value' => [ 'shareType' => Share::SHARE_TYPE_USER, 'shareWith' => $cloud->getUser(), @@ -142,6 +150,8 @@ class MailPlugin implements ISearchPlugin { if (!$this->isCurrentUser($cloud) && !$searchResult->hasResult($userType, $cloud->getUser())) { $userResults['wide'][] = [ 'label' => $displayName, + 'uuid' => $contact['UID'], + 'name' => $contact['FN'], 'value' => [ 'shareType' => Share::SHARE_TYPE_USER, 'shareWith' => $cloud->getUser(), @@ -160,6 +170,9 @@ class MailPlugin implements ISearchPlugin { } $result['exact'][] = [ 'label' => $displayName, + 'uuid' => $contact['UID'], + 'name' => $contact['FN'], + 'type' => $emailAddressType ?? '', 'value' => [ 'shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => $emailAddress, @@ -168,6 +181,9 @@ class MailPlugin implements ISearchPlugin { } else { $result['wide'][] = [ 'label' => $displayName, + 'uuid' => $contact['UID'], + 'name' => $contact['FN'], + 'type' => $emailAddressType ?? '', 'value' => [ 'shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => $emailAddress, @@ -194,6 +210,7 @@ class MailPlugin implements ISearchPlugin { if (!$searchResult->hasExactIdMatch($emailType) && filter_var($search, FILTER_VALIDATE_EMAIL)) { $result['exact'][] = [ 'label' => $search, + 'uuid' => $search, 'value' => [ 'shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => $search, diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php index e0f5298f83b..d877346b155 100644 --- a/lib/private/Collaboration/Collaborators/RemotePlugin.php +++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php @@ -30,6 +30,8 @@ use OCP\Collaboration\Collaborators\SearchResultType; use OCP\Contacts\IManager; use OCP\Federation\ICloudIdManager; use OCP\IConfig; +use OCP\IUserManager; +use OCP\IUserSession; use OCP\Share; class RemotePlugin implements ISearchPlugin { @@ -41,12 +43,20 @@ class RemotePlugin implements ISearchPlugin { private $cloudIdManager; /** @var IConfig */ private $config; + /** @var IUserManager */ + private $userManager; + /** @var string */ + private $userId = ''; - public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config) { + public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IUserManager $userManager, IUserSession $userSession) { $this->contactsManager = $contactsManager; $this->cloudIdManager = $cloudIdManager; $this->config = $config; - + $this->userManager = $userManager; + $user = $userSession->getUser(); + if ($user !== null) { + $this->userId = $user->getUID(); + } $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; } @@ -63,23 +73,47 @@ class RemotePlugin implements ISearchPlugin { } if (isset($contact['CLOUD'])) { $cloudIds = $contact['CLOUD']; - if (!is_array($cloudIds)) { + if (is_string($cloudIds)) { $cloudIds = [$cloudIds]; } $lowerSearch = strtolower($search); foreach ($cloudIds as $cloudId) { + $cloudIdType = ''; + if (\is_array($cloudId)) { + $cloudIdData = $cloudId; + $cloudId = $cloudIdData['value']; + $cloudIdType = $cloudIdData['type']; + } try { - list(, $serverUrl) = $this->splitUserRemote($cloudId); + list($remoteUser, $serverUrl) = $this->splitUserRemote($cloudId); } catch (\InvalidArgumentException $e) { continue; } + $localUser = $this->userManager->get($remoteUser); + /** + * Add local share if remote cloud id matches a local user ones + */ + if ($localUser !== null && $remoteUser !== $this->userId && $cloudId === $localUser->getCloudId() ) { + $result['wide'][] = [ + 'label' => $contact['FN'], + 'uuid' => $contact['UID'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_USER, + 'shareWith' => $remoteUser + ] + ]; + } + if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) { if (strtolower($cloudId) === $lowerSearch) { $searchResult->markExactIdMatch($resultType); } $result['exact'][] = [ 'label' => $contact['FN'] . " ($cloudId)", + 'uuid' => $contact['UID'], + 'name' => $contact['FN'], + 'type' => $cloudIdType, 'value' => [ 'shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => $cloudId, @@ -89,6 +123,9 @@ class RemotePlugin implements ISearchPlugin { } else { $result['wide'][] = [ 'label' => $contact['FN'] . " ($cloudId)", + 'uuid' => $contact['UID'], + 'name' => $contact['FN'], + 'type' => $cloudIdType, 'value' => [ 'shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => $cloudId, @@ -106,14 +143,24 @@ class RemotePlugin implements ISearchPlugin { $result['wide'] = array_slice($result['wide'], $offset, $limit); } + /** + * Add generic share with remote item for valid cloud ids that are not users of the local instance + */ if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) { - $result['exact'][] = [ - 'label' => $search, - 'value' => [ - 'shareType' => Share::SHARE_TYPE_REMOTE, - 'shareWith' => $search, - ], - ]; + try { + list($remoteUser, $serverUrl) = $this->splitUserRemote($search); + $localUser = $this->userManager->get($remoteUser); + if ($localUser === null || $search !== $localUser->getCloudId()) { + $result['exact'][] = [ + 'label' => $search, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $search, + ], + ]; + } + } catch (\InvalidArgumentException $e) { + } } $searchResult->addResultSet($resultType, $result['wide'], $result['exact']); diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php index 3ce919a4cbe..71acd27783c 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php @@ -28,6 +28,7 @@ namespace OC\Files\ObjectStore; use Icewind\Streams\CallbackWrapper; use Icewind\Streams\IteratorDirectory; use OC\Files\Cache\CacheEntry; +use OC\Files\Stream\CountReadStream; use OCP\Files\ObjectStore\IObjectStore; class ObjectStoreStorage extends \OC\Files\Storage\Common { @@ -382,25 +383,48 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { } public function writeBack($tmpFile, $path) { + $size = filesize($tmpFile); + $this->writeStream($path, fopen($tmpFile, 'r'), $size); + } + + /** + * external changes are not supported, exclusive access to the object storage is assumed + * + * @param string $path + * @param int $time + * @return false + */ + public function hasUpdated($path, $time) { + return false; + } + + public function needsPartFile() { + return false; + } + + public function file_put_contents($path, $data) { + $stream = fopen('php://temp', 'r+'); + fwrite($stream, $data); + rewind($stream); + return $this->writeStream($path, $stream, strlen($data)) > 0; + } + + public function writeStream(string $path, $stream, int $size = null): int { $stat = $this->stat($path); if (empty($stat)) { // create new file - $stat = array( + $stat = [ 'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE, - ); + ]; } // update stat with new data $mTime = time(); - $stat['size'] = filesize($tmpFile); + $stat['size'] = (int)$size; $stat['mtime'] = $mTime; $stat['storage_mtime'] = $mTime; - // run path based detection first, to use file extension because $tmpFile is only a random string $mimetypeDetector = \OC::$server->getMimeTypeDetector(); $mimetype = $mimetypeDetector->detectPath($path); - if ($mimetype === 'application/octet-stream') { - $mimetype = $mimetypeDetector->detect($tmpFile); - } $stat['mimetype'] = $mimetype; $stat['etag'] = $this->getETag($path); @@ -408,7 +432,20 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { $fileId = $this->getCache()->put($path, $stat); try { //upload to object storage - $this->objectStore->writeObject($this->getURN($fileId), fopen($tmpFile, 'r')); + if ($size === null) { + $countStream = CountReadStream::wrap($stream, function ($writtenSize) use ($fileId, &$size) { + $this->getCache()->update($fileId, [ + 'size' => $writtenSize + ]); + $size = $writtenSize; + }); + $this->objectStore->writeObject($this->getURN($fileId), $countStream); + if (is_resource($countStream)) { + fclose($countStream); + } + } else { + $this->objectStore->writeObject($this->getURN($fileId), $stream); + } } catch (\Exception $ex) { $this->getCache()->remove($path); $this->logger->logException($ex, [ @@ -417,20 +454,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { ]); throw $ex; // make this bubble up } - } - /** - * external changes are not supported, exclusive access to the object storage is assumed - * - * @param string $path - * @param int $time - * @return false - */ - public function hasUpdated($path, $time) { - return false; - } - - public function needsPartFile() { - return false; + return $size; } } diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php index b6c82f3a1df..72fe3a79792 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -54,6 +54,7 @@ use OCP\Files\InvalidPathException; use OCP\Files\ReservedWordException; use OCP\Files\Storage\ILockingStorage; use OCP\Files\Storage\IStorage; +use OCP\Files\Storage\IWriteStreamStorage; use OCP\ILogger; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; @@ -69,7 +70,7 @@ use OCP\Lock\LockedException; * Some \OC\Files\Storage\Common methods call functions which are first defined * in classes which extend it, e.g. $this->stat() . */ -abstract class Common implements Storage, ILockingStorage { +abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { use LocalTempFileTrait; @@ -809,4 +810,23 @@ abstract class Common implements Storage, ILockingStorage { public function needsPartFile() { return true; } + + /** + * fallback implementation + * + * @param string $path + * @param resource $stream + * @param int $size + * @return int + */ + public function writeStream(string $path, $stream, int $size = null): int { + $target = $this->fopen($path, 'w'); + if (!$target) { + return 0; + } + list($count, $result) = \OC_Helper::streamCopy($stream, $target); + fclose($stream); + fclose($target); + return $count; + } } diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 46b53dcf95c..5f7232e64b3 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -462,4 +462,8 @@ class Local extends \OC\Files\Storage\Common { return parent::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); } } + + public function writeStream(string $path, $stream, int $size = null): int { + return (int)file_put_contents($this->getSourcePath($path), $stream); + } } diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index 42653b2d4a6..e1c1225e0cc 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -1029,4 +1029,13 @@ class Encryption extends Wrapper { } + public function writeStream(string $path, $stream, int $size = null): int { + // always fall back to fopen + $target = $this->fopen($path, 'w'); + list($count, $result) = \OC_Helper::streamCopy($stream, $target); + fclose($stream); + fclose($target); + return $count; + } + } diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php index 56514af6d80..f21b5716467 100644 --- a/lib/private/Files/Storage/Wrapper/Jail.php +++ b/lib/private/Files/Storage/Wrapper/Jail.php @@ -29,6 +29,7 @@ use OC\Files\Cache\Wrapper\CacheJail; use OC\Files\Cache\Wrapper\JailPropagator; use OC\Files\Filesystem; use OCP\Files\Storage\IStorage; +use OCP\Files\Storage\IWriteStreamStorage; use OCP\Lock\ILockingProvider; /** @@ -515,4 +516,18 @@ class Jail extends Wrapper { $this->propagator = new JailPropagator($storage, \OC::$server->getDatabaseConnection()); return $this->propagator; } + + public function writeStream(string $path, $stream, int $size = null): int { + $storage = $this->getWrapperStorage(); + if ($storage->instanceOfStorage(IWriteStreamStorage::class)) { + /** @var IWriteStreamStorage $storage */ + return $storage->writeStream($this->getUnjailedPath($path), $stream, $size); + } else { + $target = $this->fopen($path, 'w'); + list($count, $result) = \OC_Helper::streamCopy($stream, $target); + fclose($stream); + fclose($target); + return $count; + } + } } diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php index 060c596ad65..f9c84b89fe5 100644 --- a/lib/private/Files/Storage/Wrapper/Wrapper.php +++ b/lib/private/Files/Storage/Wrapper/Wrapper.php @@ -32,9 +32,10 @@ namespace OC\Files\Storage\Wrapper; use OCP\Files\InvalidPathException; use OCP\Files\Storage\ILockingStorage; use OCP\Files\Storage\IStorage; +use OCP\Files\Storage\IWriteStreamStorage; use OCP\Lock\ILockingProvider; -class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage { +class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStreamStorage { /** * @var \OC\Files\Storage\Storage $storage */ @@ -621,4 +622,18 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage { public function needsPartFile() { return $this->getWrapperStorage()->needsPartFile(); } + + public function writeStream(string $path, $stream, int $size = null): int { + $storage = $this->getWrapperStorage(); + if ($storage->instanceOfStorage(IWriteStreamStorage::class)) { + /** @var IWriteStreamStorage $storage */ + return $storage->writeStream($path, $stream, $size); + } else { + $target = $this->fopen($path, 'w'); + list($count, $result) = \OC_Helper::streamCopy($stream, $target); + fclose($stream); + fclose($target); + return $count; + } + } } diff --git a/lib/private/Files/Stream/CountReadStream.php b/lib/private/Files/Stream/CountReadStream.php new file mode 100644 index 00000000000..93cadf8f214 --- /dev/null +++ b/lib/private/Files/Stream/CountReadStream.php @@ -0,0 +1,65 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Files\Stream; + +use Icewind\Streams\Wrapper; + +class CountReadStream extends Wrapper { + /** @var int */ + private $count; + + /** @var callback */ + private $callback; + + public static function wrap($source, $callback) { + $context = stream_context_create(array( + 'count' => array( + 'source' => $source, + 'callback' => $callback, + ) + )); + return Wrapper::wrapSource($source, $context, 'count', self::class); + } + + public function dir_opendir($path, $options) { + return false; + } + + public function stream_open($path, $mode, $options, &$opened_path) { + $context = $this->loadContext('count'); + + $this->callback = $context['callback']; + return true; + } + + public function stream_read($count) { + $result = parent::stream_read($count); + $this->count += strlen($result); + return $result; + } + + public function stream_close() { + $result = parent::stream_close(); + call_user_func($this->callback, $this->count); + return $result; + } +} diff --git a/lib/private/FullTextSearch/FullTextSearchManager.php b/lib/private/FullTextSearch/FullTextSearchManager.php new file mode 100644 index 00000000000..9a9b077cf23 --- /dev/null +++ b/lib/private/FullTextSearch/FullTextSearchManager.php @@ -0,0 +1,227 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 OC\FullTextSearch; + + +use OCP\FullTextSearch\Exceptions\FullTextSearchAppNotAvailableException; +use OCP\FullTextSearch\IFullTextSearchManager; +use OCP\FullTextSearch\Model\IIndex; +use OCP\FullTextSearch\Model\ISearchResult; +use OCP\FullTextSearch\Service\IIndexService; +use OCP\FullTextSearch\Service\IProviderService; +use OCP\FullTextSearch\Service\ISearchService; + + +/** + * Class FullTextSearchManager + * + * @package OC\FullTextSearch + */ +class FullTextSearchManager implements IFullTextSearchManager { + + + /** @var IProviderService */ + private $providerService; + + /** @var IIndexService */ + private $indexService; + + /** @var ISearchService */ + private $searchService; + + + /** + * @since 15.0.0 + * + * @param IProviderService $providerService + */ + public function registerProviderService(IProviderService $providerService) { + $this->providerService = $providerService; + } + + /** + * @since 15.0.0 + * + * @param IIndexService $indexService + */ + public function registerIndexService(IIndexService $indexService) { + $this->indexService = $indexService; + } + + /** + * @since 15.0.0 + * + * @param ISearchService $searchService + */ + public function registerSearchService(ISearchService $searchService) { + $this->searchService = $searchService; + } + + + /** + * @return IProviderService + * @throws FullTextSearchAppNotAvailableException + */ + private function getProviderService(): IProviderService { + if ($this->providerService === null) { + throw new FullTextSearchAppNotAvailableException('No IProviderService registered'); + } + + return $this->providerService; + } + + + /** + * @return IIndexService + * @throws FullTextSearchAppNotAvailableException + */ + private function getIndexService(): IIndexService { + if ($this->indexService === null) { + throw new FullTextSearchAppNotAvailableException('No IIndexService registered'); + } + + return $this->indexService; + } + + + /** + * @return ISearchService + * @throws FullTextSearchAppNotAvailableException + */ + private function getSearchService(): ISearchService { + if ($this->searchService === null) { + throw new FullTextSearchAppNotAvailableException('No ISearchService registered'); + } + + return $this->searchService; + } + + + /** + * @throws FullTextSearchAppNotAvailableException + */ + public function addJavascriptAPI() { + $this->getProviderService()->addJavascriptAPI(); + } + + + /** + * @param string $providerId + * + * @return bool + * @throws FullTextSearchAppNotAvailableException + */ + public function isProviderIndexed(string $providerId): bool { + return $this->getProviderService()->isProviderIndexed($providerId); + } + + + /** + * @param string $providerId + * @param string $documentId + * @return IIndex + * @throws FullTextSearchAppNotAvailableException + */ + public function getIndex(string $providerId, string $documentId): IIndex { + return $this->getIndexService()->getIndex($providerId, $documentId); + } + + /** + * @param string $providerId + * @param string $documentId + * @param string $userId + * @param int $status + * + * @see IIndex for available value for $status. + * + * @return IIndex + * @throws FullTextSearchAppNotAvailableException + */ + public function createIndex(string $providerId, string $documentId, string $userId, int $status = 0): IIndex { + return $this->getIndexService()->getIndex($providerId, $documentId); + } + + + /** + * @param string $providerId + * @param string $documentId + * @param int $status + * @param bool $reset + * + * @see IIndex for available value for $status. + * + * @throws FullTextSearchAppNotAvailableException + */ + public function updateIndexStatus(string $providerId, string $documentId, int $status, bool $reset = false) { + $this->getIndexService()->updateIndexStatus($providerId, $documentId, $status, $reset); + } + + /** + * @param string $providerId + * @param array $documentIds + * @param int $status + * @param bool $reset + * + * @see IIndex for available value for $status. + * + * @throws FullTextSearchAppNotAvailableException + */ + public function updateIndexesStatus(string $providerId, array $documentIds, int $status, bool $reset = false) { + $this->getIndexService()->updateIndexesStatus($providerId, $documentIds, $status, $reset); + } + + + /** + * @param IIndex[] $indexes + * + * @throws FullTextSearchAppNotAvailableException + */ + public function updateIndexes(array $indexes) { + $this->getIndexService()->updateIndexes($indexes); + } + + + /** + * @param array $request + * @param string $userId + * + * @return ISearchResult[] + * @throws FullTextSearchAppNotAvailableException + */ + public function search(array $request, string $userId = ''): array { + $searchRequest = $this->getSearchService()->generateSearchRequest($request); + + return $this->getSearchService()->search($userId, $searchRequest); + } + + +} + diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php index 4c56a316042..05a884a67fa 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -185,12 +185,13 @@ EOF; </table> EOF; + // note: listBegin (like bodyBegin) is not processed through sprintf, so "%" is not escaped as "%%". (bug #12151) protected $listBegin = <<<EOF -<table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%%"> +<table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%"> <tbody> <tr style="padding:0;text-align:left;vertical-align:top"> <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> - <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"> EOF; protected $listItem = <<<EOF diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php index 6f148bc0c6e..df23b669365 100644 --- a/lib/private/Mail/Mailer.php +++ b/lib/private/Mail/Mailer.php @@ -274,7 +274,11 @@ class Mailer implements IMailer { $binaryPath = '/var/qmail/bin/sendmail'; break; default: - $binaryPath = '/usr/sbin/sendmail'; + $sendmail = \OC_Helper::findBinaryPath('sendmail'); + if ($sendmail === null) { + $sendmail = '/usr/sbin/sendmail'; + } + $binaryPath = $sendmail; break; } diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index 86579e3480b..1f7decf2b79 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -298,19 +298,23 @@ class Generator { if ($height !== $maxHeight && $width !== $maxWidth) { /* - * Scale to the nearest power of two + * Scale to the nearest power of four */ - $pow2height = 2 ** ceil(log($height) / log(2)); - $pow2width = 2 ** ceil(log($width) / log(2)); + $pow4height = 4 ** ceil(log($height) / log(4)); + $pow4width = 4 ** ceil(log($width) / log(4)); - $ratioH = $height / $pow2height; - $ratioW = $width / $pow2width; + // Minimum size is 64 + $pow4height = max($pow4height, 64); + $pow4width = max($pow4width, 64); + + $ratioH = $height / $pow4height; + $ratioW = $width / $pow4width; if ($ratioH < $ratioW) { - $width = $pow2width; + $width = $pow4width; $height /= $ratioW; } else { - $height = $pow2height; + $height = $pow4height; $width /= $ratioH; } } diff --git a/lib/private/Repair.php b/lib/private/Repair.php index ad9662ca1d7..01724fd6a38 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -39,6 +39,7 @@ use OC\Repair\NC11\FixMountStorages; use OC\Repair\NC13\AddLogRotateJob; use OC\Repair\NC14\AddPreviewBackgroundCleanupJob; use OC\Repair\NC14\RepairPendingCronJobs; +use OC\Repair\NC15\SetVcardDatabaseUID; use OC\Repair\OldGroupMembershipShares; use OC\Repair\Owncloud\DropAccountTermsTable; use OC\Repair\Owncloud\SaveAccountsTableData; @@ -139,6 +140,7 @@ class Repair implements IOutput{ new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()), new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()), new RepairPendingCronJobs(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), + new SetVcardDatabaseUID(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), ]; } diff --git a/lib/private/Repair/NC15/SetVcardDatabaseUID.php b/lib/private/Repair/NC15/SetVcardDatabaseUID.php new file mode 100644 index 00000000000..ccf6c47cbc8 --- /dev/null +++ b/lib/private/Repair/NC15/SetVcardDatabaseUID.php @@ -0,0 +1,137 @@ +<?php +/** + * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @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 OC\Repair\NC15; + +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; +use Sabre\VObject\Reader; + +class SetVcardDatabaseUID implements IRepairStep { + const MAX_ROWS = 1000; + + /** @var IDBConnection */ + private $connection; + + /** @var IConfig */ + private $config; + + private $updateQuery; + + public function __construct(IDBConnection $connection, IConfig $config) { + $this->connection = $connection; + $this->config = $config; + } + + public function getName() { + return 'Extract the vcard uid and store it in the db'; + } + + /** + * @return \Generator + * @suppress SqlInjectionChecker + */ + private function getInvalidEntries() { + $builder = $this->connection->getQueryBuilder(); + + $builder->select('id', 'carddata') + ->from('cards') + ->where($builder->expr()->isNull('uid')) + ->setMaxResults(self::MAX_ROWS); + + do { + $result = $builder->execute(); + $rows = $result->fetchAll(); + foreach ($rows as $row) { + yield $row; + } + $result->closeCursor(); + } while (count($rows) > 0); + } + + /** + * Extract UID from vcard + * + * @param string $cardData the vcard raw data + * @return string the uid or empty if none + */ + private function getUID(string $cardData): string { + $vCard = Reader::read($cardData); + if ($vCard->UID) { + $uid = $vCard->UID->getValue(); + return $uid; + } + + return ''; + } + + /** + * @param int $id + * @param string $uid + */ + private function update(int $id, string $uid) { + if (!$this->updateQuery) { + $builder = $this->connection->getQueryBuilder(); + + $this->updateQuery = $builder->update('cards') + ->set('uid', $builder->createParameter('uid')) + ->where($builder->expr()->eq('id', $builder->createParameter('id'))); + } + + $this->updateQuery->setParameter('id', $id); + $this->updateQuery->setParameter('uid', $uid); + + $this->updateQuery->execute(); + } + + private function repair(): int { + $this->connection->beginTransaction(); + $entries = $this->getInvalidEntries(); + $count = 0; + foreach ($entries as $entry) { + $count++; + $uid = $this->getUID($entry['carddata']); + $this->update($entry['id'], $uid); + } + $this->connection->commit(); + + return $count; + } + + private function shouldRun() { + $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0.0'); + + // was added to 15.0.0.2 + return version_compare($versionFromBeforeUpdate, '15.0.0.2', '<='); + } + + public function run(IOutput $output) { + if ($this->shouldRun()) { + $count = $this->repair(); + + $output->info('Fixed ' . $count . ' vcards'); + } + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 32d7705919c..204345708b9 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -82,6 +82,7 @@ use OC\Files\Node\LazyRoot; use OC\Files\Node\Root; use OC\Files\Storage\StorageFactory; use OC\Files\View; +use OC\FullTextSearch\FullTextSearchManager; use OC\Http\Client\ClientService; use OC\IntegrityCheck\Checker; use OC\IntegrityCheck\Helpers\AppLocator; @@ -138,6 +139,7 @@ use OCP\Federation\ICloudIdManager; use OCP\Authentication\LoginCredentials\IStore; use OCP\Files\NotFoundException; use OCP\Files\Storage\IStorageFactory; +use OCP\FullTextSearch\IFullTextSearchManager; use OCP\GlobalScale\IConfig; use OCP\ICacheFactory; use OCP\IDBConnection; @@ -758,7 +760,7 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('TrustedDomainHelper', function ($c) { return new TrustedDomainHelper($this->getConfig()); }); - $this->registerService('Throttler', function (Server $c) { + $this->registerService(Throttler::class, function (Server $c) { return new Throttler( $c->getDatabaseConnection(), new TimeFactory(), @@ -766,6 +768,7 @@ class Server extends ServerContainer implements IServerContainer { $c->getConfig() ); }); + $this->registerAlias('Throttler', Throttler::class); $this->registerService('IntegrityCodeChecker', function (Server $c) { // IConfig and IAppManager requires a working database. This code // might however be called when ownCloud is not yet setup. @@ -1182,7 +1185,8 @@ class Server extends ServerContainer implements IServerContainer { return new StorageFactory(); }); - $this->registerAlias(IDashboardManager::class, Dashboard\DashboardManager::class); + $this->registerAlias(IDashboardManager::class, DashboardManager::class); + $this->registerAlias(IFullTextSearchManager::class, FullTextSearchManager::class); $this->connectDispatcher(); } diff --git a/lib/private/Settings/Admin/Sharing.php b/lib/private/Settings/Admin/Sharing.php index dfc0b11478b..ee6a64c85bf 100644 --- a/lib/private/Settings/Admin/Sharing.php +++ b/lib/private/Settings/Admin/Sharing.php @@ -32,6 +32,7 @@ use OCP\Constants; use OCP\IConfig; use OCP\IL10N; use OCP\Settings\ISettings; +use OCP\Share\IManager; use OCP\Util; class Sharing implements ISettings { @@ -41,12 +42,16 @@ class Sharing implements ISettings { /** @var IL10N */ private $l; + /** @var IManager */ + private $shareManager; + /** * @param IConfig $config */ - public function __construct(IConfig $config, IL10N $l) { + public function __construct(IConfig $config, IL10N $l, IManager $shareManager) { $this->config = $config; $this->l = $l; + $this->shareManager = $shareManager; } /** @@ -65,7 +70,7 @@ class Sharing implements ISettings { 'allowResharing' => $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes'), 'allowShareDialogUserEnumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'), 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(), - 'onlyShareWithGroupMembers' => Share::shareWithGroupMembersOnly(), + 'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(), 'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'), 'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'), 'shareExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'), diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index 36912dcafe3..76a6a1baeca 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -341,7 +341,7 @@ class Share extends Constants { } $uidOwner = \OC_User::getUser(); - $shareWithinGroupOnly = self::shareWithGroupMembersOnly(); + $shareWithinGroupOnly = \OC::$server->getConfig()->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; if (is_null($itemSourceName)) { $itemSourceName = $itemSource; @@ -2055,15 +2055,6 @@ class Share extends Constants { } /** - * check if user can only share with group members - * @return bool - */ - public static function shareWithGroupMembersOnly() { - $value = \OC::$server->getConfig()->getAppValue('core', 'shareapi_only_share_with_group_members', 'no'); - return $value === 'yes'; - } - - /** * @return bool */ public static function isDefaultExpireDateEnabled() { @@ -2104,15 +2095,6 @@ class Share extends Constants { } /** - * @param IConfig $config - * @return bool - */ - public static function enforcePassword(IConfig $config) { - $enforcePassword = $config->getAppValue('core', 'shareapi_enforce_links_password', 'no'); - return $enforcePassword === 'yes'; - } - - /** * @param string $password * @throws \Exception */ diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index 9c5d78a5958..589b64fc58a 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -146,6 +146,8 @@ class DefaultShareProvider implements IShareProvider { //Set the GID of the group we share with $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith())); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + //set label for public link + $qb->setValue('label', $qb->createNamedParameter($share->getLabel())); //Set the token of the share $qb->setValue('token', $qb->createNamedParameter($share->getToken())); @@ -154,6 +156,8 @@ class DefaultShareProvider implements IShareProvider { $qb->setValue('password', $qb->createNamedParameter($share->getPassword())); } + $qb->setValue('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL)); + //If an expiration date is set store it if ($share->getExpirationDate() !== null) { $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime')); @@ -225,6 +229,9 @@ class DefaultShareProvider implements IShareProvider { * * @param \OCP\Share\IShare $share * @return \OCP\Share\IShare The share object + * @throws ShareNotFound + * @throws \OCP\Files\InvalidPathException + * @throws \OCP\Files\NotFoundException */ public function update(\OCP\Share\IShare $share) { @@ -288,6 +295,7 @@ class DefaultShareProvider implements IShareProvider { $qb->update('share') ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) ->set('password', $qb->createNamedParameter($share->getPassword())) + ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL)) ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner())) ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) ->set('permissions', $qb->createNamedParameter($share->getPermissions())) @@ -296,6 +304,8 @@ class DefaultShareProvider implements IShareProvider { ->set('token', $qb->createNamedParameter($share->getToken())) ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) ->set('note', $qb->createNamedParameter($share->getNote())) + ->set('label', $qb->createNamedParameter($share->getLabel())) + ->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT) ->execute(); } @@ -918,7 +928,8 @@ class DefaultShareProvider implements IShareProvider { ->setPermissions((int)$data['permissions']) ->setTarget($data['file_target']) ->setNote($data['note']) - ->setMailSend((bool)$data['mail_send']); + ->setMailSend((bool)$data['mail_send']) + ->setLabel($data['label']); $shareTime = new \DateTime(); $shareTime->setTimestamp((int)$data['stime']); @@ -930,6 +941,7 @@ class DefaultShareProvider implements IShareProvider { $share->setSharedWith($data['share_with']); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { $share->setPassword($data['password']); + $share->setSendPasswordByTalk((bool)$data['password_by_talk']); $share->setToken($data['token']); } @@ -953,6 +965,7 @@ class DefaultShareProvider implements IShareProvider { } $share->setProviderId($this->identifier()); + $share->setHideDownload((int)$data['hide_download'] === 1); return $share; } diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index 71c0453d9e5..f9b548c1adf 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -30,6 +30,7 @@ use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\IUserManager; use OCP\Share\Exceptions\IllegalIDChangeException; +use OCP\Share\IShare; class Share implements \OCP\Share\IShare { @@ -75,6 +76,8 @@ class Share implements \OCP\Share\IShare { private $shareTime; /** @var bool */ private $mailSend; + /** @var string */ + private $label = ''; /** @var IRootFolder */ private $rootFolder; @@ -85,6 +88,9 @@ class Share implements \OCP\Share\IShare { /** @var ICacheEntry|null */ private $nodeCacheEntry; + /** @var bool */ + private $hideDownload = false; + public function __construct(IRootFolder $rootFolder, IUserManager $userManager) { $this->rootFolder = $rootFolder; $this->userManager = $userManager; @@ -333,6 +339,21 @@ class Share implements \OCP\Share\IShare { /** * @inheritdoc */ + public function setLabel($label) { + $this->label = $label; + return $this; + } + + /** + * @inheritdoc + */ + public function getLabel() { + return $this->label; + } + + /** + * @inheritdoc + */ public function setExpirationDate($expireDate) { //TODO checks @@ -514,4 +535,13 @@ class Share implements \OCP\Share\IShare { public function getNodeCacheEntry() { return $this->nodeCacheEntry; } + + public function setHideDownload(bool $hide): IShare { + $this->hideDownload = $hide; + return $this; + } + + public function getHideDownload(): bool { + return $this->hideDownload; + } } diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php index b691a8a64cb..ad9ff0b6757 100644 --- a/lib/private/Template/JSConfigHelper.php +++ b/lib/private/Template/JSConfigHelper.php @@ -70,6 +70,9 @@ class JSConfigHelper { /** @var CapabilitiesManager */ private $capabilitiesManager; + /** @var array user back-ends excluded from password verification */ + private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true]; + /** * @param IL10N $l * @param Defaults $defaults @@ -158,7 +161,7 @@ class JSConfigHelper { $array = [ "oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false', "oc_isadmin" => $this->groupManager->isAdmin($uid) ? 'true' : 'false', - "backendAllowsPasswordConfirmation" => $userBackend === 'user_saml'? 'false' : 'true', + "backendAllowsPasswordConfirmation" => !isset($this->excludedUserBackEnds[$userBackend]) ? 'true' : 'false', "oc_dataURL" => is_string($dataLocation) ? "\"".$dataLocation."\"" : 'false', "oc_webroot" => "\"".\OC::$WEBROOT."\"", "oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 8a2b1cd188c..4b4723be94f 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -38,7 +38,6 @@ use OC\DB\MigrationService; use OC\Hooks\BasicEmitter; use OC\IntegrityCheck\Checker; use OC_App; -use OCP\BackgroundJob\IJobList; use OCP\IConfig; use OCP\ILogger; use OCP\Util; @@ -67,9 +66,6 @@ class Updater extends BasicEmitter { /** @var Installer */ private $installer; - /** @var IJobList */ - private $jobList; - private $logLevelNames = [ 0 => 'Debug', 1 => 'Info', @@ -78,16 +74,20 @@ class Updater extends BasicEmitter { 4 => 'Fatal', ]; + /** + * @param IConfig $config + * @param Checker $checker + * @param ILogger $log + * @param Installer $installer + */ public function __construct(IConfig $config, Checker $checker, - ILogger $log, - Installer $installer, - IJobList $jobList) { + ILogger $log = null, + Installer $installer) { $this->log = $log; $this->config = $config; $this->checker = $checker; $this->installer = $installer; - $this->jobList = $jobList; } /** @@ -114,11 +114,6 @@ class Updater extends BasicEmitter { $installedVersion = $this->config->getSystemValue('version', '0.0.0'); $currentVersion = implode('.', \OCP\Util::getVersion()); - // see https://github.com/nextcloud/server/issues/9992 for potential problem - if (version_compare($installedVersion, '14.0.0.9', '>=')) { - $this->waitForCronToFinish(); - } - $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core')); $success = true; @@ -617,12 +612,6 @@ class Updater extends BasicEmitter { }); } - private function waitForCronToFinish() { - while ($this->jobList->isAnyJobRunning()) { - $this->emit('\OC\Updater', 'waitForCronToFinish'); - sleep(5); - } - } } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index a9c638dca93..674f38e2401 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -38,6 +38,7 @@ namespace OC\User; use OC; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; use OC\Authentication\Exceptions\PasswordLoginForbiddenException; @@ -401,7 +402,13 @@ class Session implements IUserSession, Emitter { $this->manager->emit('\OC\User', 'preLogin', array($user, $password)); } - $isTokenPassword = $this->isTokenPassword($password); + try { + $isTokenPassword = $this->isTokenPassword($password); + } catch (ExpiredTokenException $e) { + // Just return on an expired token no need to check further or record a failed login + return false; + } + if (!$isTokenPassword && $this->isTokenAuthEnforced()) { throw new PasswordLoginForbiddenException(); } @@ -474,11 +481,14 @@ class Session implements IUserSession, Emitter { * * @param string $password * @return boolean + * @throws ExpiredTokenException */ public function isTokenPassword($password) { try { $this->tokenProvider->getToken($password); return true; + } catch (ExpiredTokenException $e) { + throw $e; } catch (InvalidTokenException $ex) { return false; } diff --git a/lib/public/Files/Storage/IWriteStreamStorage.php b/lib/public/Files/Storage/IWriteStreamStorage.php new file mode 100644 index 00000000000..39a28dd037b --- /dev/null +++ b/lib/public/Files/Storage/IWriteStreamStorage.php @@ -0,0 +1,40 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\Files\Storage; + +/** + * Interface that adds the ability to write a stream directly to file + * + * @since 15.0.0 + */ +interface IWriteStreamStorage extends IStorage { + /** + * Write the data from a stream to a file + * + * @param string $path + * @param resource $stream + * @param int|null $size the size of the stream if known in advance + * @return int the number of bytes written + * @since 15.0.0 + */ + public function writeStream(string $path, $stream, int $size = null): int; +} diff --git a/lib/public/Files_FullTextSearch/Model/AFilesDocument.php b/lib/public/Files_FullTextSearch/Model/AFilesDocument.php new file mode 100644 index 00000000000..3eed956df84 --- /dev/null +++ b/lib/public/Files_FullTextSearch/Model/AFilesDocument.php @@ -0,0 +1,112 @@ +<?php +declare(strict_types=1); + + +/** + * Files_FullTextSearch - Index the content of your files + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\Files_FullTextSearch\Model; + + +use OCP\FullTextSearch\Model\IndexDocument; + + +/** + * Abstract Class AFilesDocument + * + * This is mostly used by 3rd party apps that want to complete the IndexDocument + * with more information about a file before its index: + * + * \OC::$server->getEventDispatcher()->addListener( + * '\OCA\Files_FullTextSearch::onFileIndexing', + * function(GenericEvent $e) { + * //@var \OCP\Files\Node $file + * $file = $e->getArgument('file'); + * + * // @var \OCP\Files_FullTextSearch\Model\AFilesDocument $document + * $document = $e->getArgument('document'); + * + * } + * ); + * + * @since 15.0.0 + * + * @package OCP\Files_FullTextSearch\Model + */ +abstract class AFilesDocument extends IndexDocument { + + + /** + * Returns the owner of the document/file. + * + * @since 15.0.0 + * + * @return string + */ + abstract public function getOwnerId(): string; + + + /** + * Returns the current viewer of the document/file. + * + * @since 15.0.0 + * + * @return string + */ + abstract public function getViewerId(): string; + + + /** + * Returns the type of the document/file. + * + * @since 15.0.0 + * + * @return string \OCP\Files\FileInfo::TYPE_FILE|\OCP\Files\FileInfo::TYPE_FOLDER + */ + abstract public function getType(): string; + + + /** + * Returns the mimetype of the document/file. + * + * @since 15.0.0 + * + * @return string + */ + abstract public function getMimetype(): string; + + /** + * Returns the path of the document/file. + * + * @since 15.0.0 + * + * @return string + */ + abstract public function getPath(): string; + + +} + diff --git a/lib/public/FullTextSearch/Exceptions/FullTextSearchAppNotAvailableException.php b/lib/public/FullTextSearch/Exceptions/FullTextSearchAppNotAvailableException.php new file mode 100644 index 00000000000..4363376f0f4 --- /dev/null +++ b/lib/public/FullTextSearch/Exceptions/FullTextSearchAppNotAvailableException.php @@ -0,0 +1,42 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 OCP\FullTextSearch\Exceptions; + +/** + * @since 15.0.0 + * + * Class FullTextSearchAppNotAvailableException + * + * @package OCP\FullTextSearch\Exceptions + */ +class FullTextSearchAppNotAvailableException extends \Exception { +} + diff --git a/lib/public/FullTextSearch/IFullTextSearchManager.php b/lib/public/FullTextSearch/IFullTextSearchManager.php new file mode 100644 index 00000000000..1027f7ade75 --- /dev/null +++ b/lib/public/FullTextSearch/IFullTextSearchManager.php @@ -0,0 +1,186 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 OCP\FullTextSearch; + + +use OCP\FullTextSearch\Model\IIndex; +use OCP\FullTextSearch\Model\ISearchResult; +use OCP\FullTextSearch\Service\IIndexService; +use OCP\FullTextSearch\Service\IProviderService; +use OCP\FullTextSearch\Service\ISearchService; + + +/** + * Interface IFullTextSearchManager + * + * Should be used to manage FullTextSearch from the app that contains your + * Content Provider/Search Platform. + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch + */ +interface IFullTextSearchManager { + + + /** + * Register a IProviderService. + * + * @since 15.0.0 + * + * @param IProviderService $providerService + */ + public function registerProviderService(IProviderService $providerService); + + /** + * Register a IIndexService. + * + * @since 15.0.0 + * + * @param IIndexService $indexService + */ + public function registerIndexService(IIndexService $indexService); + + /** + * Register a ISearchService. + * + * @since 15.0.0 + * + * @param ISearchService $searchService + */ + public function registerSearchService(ISearchService $searchService); + + + /** + * Add the Javascript API in the navigation page of an app. + * Needed to replace the default search. + * + * @since 15.0.0 + */ + public function addJavascriptAPI(); + + + /** + * Check if the provider $providerId is already indexed. + * + * @since 15.0.0 + * + * @param string $providerId + * + * @return bool + */ + public function isProviderIndexed(string $providerId): bool; + + + /** + * Retrieve an Index from the database, based on the Id of the Provider + * and the Id of the Document + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + * + * @return IIndex + */ + public function getIndex(string $providerId, string $documentId): IIndex; + + + /** + * Create a new Index. + * + * This method must be called when a new document is created. + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + * @param string $userId + * @param int $status + * + * @return IIndex + */ + public function createIndex(string $providerId, string $documentId, string $userId, int $status = 0): IIndex; + + + /** + * Update the status of an Index. status is a bitflag, setting $reset to + * true will reset the status to the value defined in the parameter. + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + * @param int $status + * @param bool $reset + */ + public function updateIndexStatus(string $providerId, string $documentId, int $status, bool $reset = false); + + + /** + * Update the status of an array of Index. status is a bit flag, setting $reset to + * true will reset the status to the value defined in the parameter. + * + * @since 15.0.0 + * + * @param string $providerId + * @param array $documentIds + * @param int $status + * @param bool $reset + */ + public function updateIndexesStatus(string $providerId, array $documentIds, int $status, bool $reset = false); + + /** + * Update an array of Index. + * + * @since 15.0.0 + * + * @param IIndex[] $indexes + */ + public function updateIndexes(array $indexes); + + /** + * Search using an array as request. If $userId is empty, will use the + * current session. + * + * @see ISearchService::generateSearchRequest + * + * @since 15.0.0 + * + * @param array $request + * @param string $userId + * @return ISearchResult[] + */ + public function search(array $request, string $userId = ''): array; + + +} + diff --git a/lib/public/FullTextSearch/IFullTextSearchPlatform.php b/lib/public/FullTextSearch/IFullTextSearchPlatform.php new file mode 100644 index 00000000000..f3f9a35bae2 --- /dev/null +++ b/lib/public/FullTextSearch/IFullTextSearchPlatform.php @@ -0,0 +1,227 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch; + + +use OCP\FullTextSearch\Model\DocumentAccess; +use OCP\FullTextSearch\Model\IIndex; +use OCP\FullTextSearch\Model\IndexDocument; +use OCP\FullTextSearch\Model\IRunner; +use OCP\FullTextSearch\Model\ISearchResult; + + +/** + * Interface IFullTextSearchPlatform + * + * This interface must be use when creating a Search Platform for FullTextSearch. + * + * A Search Platform is an extension to the FullTextSearch that will act as a + * a gateway between FullTextSearch and a search server (ie. ElasticSearch, + * Solr, ...) + * + * Multiple Search Platform can exist at the same time in Nextcloud, however only + * one Search Platform will be used by FullTextSearch. + * Administrator must select at least one Search Platform to be used by + * FullTextSearch in the admin settings page. + * + * The content provided by FullTextSearch comes in chunk from multiple Content + * Provider. Each chunk is identified by the ID of the Content Provider, and the + * ID of the document. + * + * + * To oversimplify the mechanism: + * + * - When indexing, FullTextSearch will send providerId, documentId, content. + * - When searching within the content of a Content Provider, identified by its + * providerId, FullTextSearch expect documentId as result. + * + * + * The Search Platform ia a PHP class that implement this interface and is defined + * in appinfo/info.xml of the app that contains that class: + * + * <fulltextsearch> + * <platform>OCA\YourApp\YourSearchPlatform</platform> + * </fulltextsearch> + * + * Multiple Search Platform can be defined in a single app. + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch + */ +interface IFullTextSearchPlatform { + + + /** + * Must returns a unique Id used to identify the Search Platform. + * Id must contains only alphanumeric chars, with no space. + * + * @since 15.0.0 + * + * @return string + */ + public function getId(): string; + + + /** + * Must returns a descriptive name of the Search Platform. + * This is used mainly in the admin settings page to display the list of + * available Search Platform + * + * @since 15.0.0 + * + * @return string + */ + public function getName(): string; + + + /** + * should returns the current configuration of the Search Platform. + * This is used to display the configuration when using the + * ./occ fulltextsearch:check command line. + * + * @since 15.0.0 + * + * @return array + */ + public function getConfiguration(): array; + + + /** + * Set the wrapper of the currently executed process. + * Because the index process can be long and heavy, and because errors can + * be encountered during the process, the IRunner is a wrapper that allow the + * Search Platform to communicate with the process initiated by + * FullTextSearch. + * + * The IRunner is coming with some methods so the Search Platform can + * returns important information and errors to be displayed to the admin. + * + * @since 15.0.0 + * + * @param IRunner $runner + */ + public function setRunner(IRunner $runner); + + + /** + * Called when FullTextSearch is loading your Search Platform. + * + * @since 15.0.0 + */ + public function loadPlatform(); + + + /** + * Called to check that your Search Platform is correctly configured and that + * This is also the right place to check that the Search Service is available. + * + * @since 15.0.0 + * + * @return bool + */ + public function testPlatform(): bool; + + + /** + * Called before an index is initiated. + * Best place to initiate some stuff on the Search Server (mapping, ...) + * + * @since 15.0.0 + */ + public function initializeIndex(); + + + /** + * Reset the indexes for a specific providerId. + * $providerId can be 'all' if it is a global reset. + * + * @since 15.0.0 + * + * @param string $providerId + */ + public function resetIndex(string $providerId); + + + /** + * Deleting some IIndex, sent in an array + * + * @see IIndex + * + * @since 15.0.0 + * + * @param IIndex[] $indexes + */ + public function deleteIndexes(array $indexes); + + + /** + * Indexing a document. + * + * @see IndexDocument + * + * @since 15.0.0 + * + * @param IndexDocument $document + * + * @return IIndex + */ + public function indexDocument(IndexDocument $document): IIndex; + + + /** + * Searching documents, ISearchResult should be updated with the result of + * the search. + * + * @since 15.0.0 + * + * @param ISearchResult $result + * @param DocumentAccess $access + */ + public function searchRequest(ISearchResult $result, DocumentAccess $access); + + + /** + * Return a document based on its Id and the Provider. + * This is used when an admin execute ./occ fulltextsearch:document:platform + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + * + * @return IndexDocument + */ + public function getDocument(string $providerId, string $documentId): IndexDocument; + + +} + diff --git a/lib/public/FullTextSearch/IFullTextSearchProvider.php b/lib/public/FullTextSearch/IFullTextSearchProvider.php new file mode 100644 index 00000000000..890b57d84c9 --- /dev/null +++ b/lib/public/FullTextSearch/IFullTextSearchProvider.php @@ -0,0 +1,304 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch; + + +use OCP\FullTextSearch\Model\IIndex; +use OCP\FullTextSearch\Model\IIndexOptions; +use OCP\FullTextSearch\Model\IndexDocument; +use OCP\FullTextSearch\Model\IRunner; +use OCP\FullTextSearch\Model\ISearchRequest; +use OCP\FullTextSearch\Model\ISearchResult; +use OCP\FullTextSearch\Model\SearchTemplate; + + +/** + * Interface IFullTextSearchProvider + * + * This interface must be use when creating a Content Provider for FullTextSearch. + * + * A Content Provider is an extension to the FullTextSearch that will extract and + * provide content to the FullTextSearch. + * + * There is no limit to the number of Content Provider that can be integrated to + * FullTextSearch. Each Content Provider corresponding to a type of content + * available in Nextcloud (files, bookmarks, notes, deck cards, mails, ...) + * + * Content is split in document identified by an ID and the ID of the Content + * Provider. The content is indexed by a Search Platform that will returns a + * documentId as a result on a search request. + * + * + * To oversimplify the mechanism: + * + * - When indexing, FullTextSearch will ask for documents to every Content Provider. + * - On search, results from the Search Platform, identified by documentId, will + * be improved by each relative Content Provider. + * + * + * The Content Provider is a PHP class that implement this interface and is defined + * in appinfo/info.xml of the app that contains that class: + * + * <fulltextsearch> + * <provider>OCA\YourApp\YourContentProvider</provider> + * </fulltextsearch> + * + * Multiple Content Provider can be defined in a single app. + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch + */ +interface IFullTextSearchProvider { + + + /** + * Must returns a unique Id used to identify the Content Provider. + * Id must contains only alphanumeric chars, with no space. + * + * @since 15.0.0 + * + * @return string + */ + public function getId(): string; + + + /** + * Must returns a descriptive name of the Content Provider. + * This is used in multiple places, so better use a clear display name. + * + * @since 15.0.0 + * + * @return string + */ + public function getName(): string; + + + /** + * Should returns the current configuration of the Content Provider. + * This is used to display the configuration when using the + * ./occ fulltextsearch:check command line. + * + * @since 15.0.0 + * + * @return array + */ + public function getConfiguration(): array; + + + /** + * Must returns a SearchTemplate that contains displayable items and + * available options to users when searching. + * + * @see SearchTemplate + * + * @since 15.0.0 + * + * @return SearchTemplate + */ + public function getSearchTemplate(): SearchTemplate; + + + /** + * Called when FullTextSearch is loading your Content Provider. + * + * @since 15.0.0 + */ + public function loadProvider(); + + + /** + * Set the wrapper of the currently executed process. + * Because the index process can be long and heavy, and because errors can + * be encountered during the process, the IRunner is a wrapper that allow the + * Content Provider to communicate with the process initiated by + * FullTextSearch. + * + * The IRunner is coming with some methods so the Content Provider can + * returns important information and errors to be displayed to the admin. + * + * @since 15.0.0 + * + * @param IRunner $runner + */ + public function setRunner(IRunner $runner); + + + /** + * This method is called when the administrator specify options when running + * the ./occ fulltextsearch:index or ./occ fulltextsearch:live + * + * @since 15.0.0 + * + * @param IIndexOptions $options + */ + public function setIndexOptions(IIndexOptions $options); + + + /** + * Returns all indexable document for a user as an array of IndexDocument. + * + * There is no need to fill each IndexDocument with content; at this point, + * only fill the object with the minimum information to not waste memory while + * still being able to identify the document it is referring to. + * + * FullTextSearch will call 2 other methods of this interface for each + * IndexDocument of the array, prior to their indexing: + * + * - first, to compare the date of the last index, + * - then, to fill each IndexDocument with complete data + * + * @see IndexDocument + * + * @since 15.0.0 + * + * @param string $userId + * + * @return IndexDocument[] + */ + public function generateIndexableDocuments(string $userId): array; + + + /** + * Called to verify that the document is not already indexed and that the + * old index is not up-to-date, using the IIndex from + * IndexDocument->getIndex() + * + * Returning true will not queue the current IndexDocument to any further + * operation and will continue on the next element from the list returned by + * generateIndexableDocuments(). + * + * @since 15.0.0 + * + * @param IndexDocument $document + * + * @return bool + */ + public function isDocumentUpToDate(IndexDocument $document): bool; + + + /** + * Must fill IndexDocument with all information relative to the document, + * before its indexing by the Search Platform. + * + * Method is called for each element returned previously by + * generateIndexableDocuments(). + * + * @see IndexDocument + * + * @since 15.0.0 + * + * @param IndexDocument $document + */ + public function fillIndexDocument(IndexDocument $document); + + + /** + * The Search Provider must create and return an IndexDocument + * based on the IIndex and its status. The IndexDocument must contains all + * information as it will be send for indexing. + * + * Method is called during a cron or a ./occ fulltextsearch:live after a + * new document is created, or an old document is set as modified. + * + * @since 15.0.0 + * + * @param IIndex $index + * + * @return IndexDocument + */ + public function updateDocument(IIndex $index): IndexDocument; + + + /** + * Called when an index is initiated by the administrator. + * This is should only be used in case of a specific mapping is needed. + * (ie. _almost_ never) + * + * @since 15.0.0 + * + * @param IFullTextSearchPlatform $platform + */ + public function onInitializingIndex(IFullTextSearchPlatform $platform); + + + /** + * Called when administrator is resetting the index. + * This is should only be used in case of a specific mapping has been + * created. + * + * @since 15.0.0 + * + * @param IFullTextSearchPlatform $platform + */ + public function onResettingIndex(IFullTextSearchPlatform $platform); + + + /** + * Method is called when a search request is initiated by a user, prior to + * be sent to the Search Platform. + * + * Your Content Provider can interact with the ISearchRequest to apply the + * search options and make the search more precise. + * + * @see ISearchRequest + * + * @since 15.0.0 + * + * @param ISearchRequest $searchRequest + */ + public function improveSearchRequest(ISearchRequest $searchRequest); + + + /** + * Method is called after results of a search are returned by the + * Search Platform. + * + * Your Content Provider can detail each entry with local data to improve + * the display of the search result. + * + * @see ISearchResult + * + * @since 15.0.0 + * + * @param ISearchResult $searchResult + */ + public function improveSearchResult(ISearchResult $searchResult); + + + /** + * not used yet. + * + * @since 15.0.0 + */ + public function unloadProvider(); + +} diff --git a/lib/public/FullTextSearch/Model/DocumentAccess.php b/lib/public/FullTextSearch/Model/DocumentAccess.php new file mode 100644 index 00000000000..ef199fb7385 --- /dev/null +++ b/lib/public/FullTextSearch/Model/DocumentAccess.php @@ -0,0 +1,363 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +use JsonSerializable; + + +/** + * Class DocumentAccess + * + * This object is used as a data transfer object when + * + * - indexing a document, + * - generating a search request. + * + * During the index, it is used to define which users, groups, circles, ... + * have access to the IndexDocument + * + * During the search, it is internally use to define to which group, circles, ... + * a user that perform the search belongs to. + * + * @see IndexDocument::setAccess + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Model + */ +final class DocumentAccess implements JsonSerializable { + + /** @var string */ + private $ownerId; + + /** @var string */ + private $viewerId = ''; + + /** @var array */ + private $users = []; + + /** @var array */ + private $groups = []; + + /** @var array */ + private $circles = []; + + /** @var array */ + private $links = []; + + + /** + * Owner of the document can be set at the init of the object. + * + * @since 15.0.0 + * + * DocumentAccess constructor. + * + * @param string $ownerId + */ + public function __construct(string $ownerId = '') { + $this->setOwnerId($ownerId); + } + + + /** + * Set the Owner of the document. + * + * @since 15.0.0 + * + * @param string $ownerId + * + * @return DocumentAccess + */ + public function setOwnerId(string $ownerId) { + $this->ownerId = $ownerId; + + return $this; + } + + /** + * Get the Owner of the document. + * + * @since 15.0.0 + * + * @return string + */ + public function getOwnerId(): string { + return $this->ownerId; + } + + + /** + * Set the viewer of the document. + * + * @since 15.0.0 + * + * @param string $viewerId + * + * @return DocumentAccess + */ + public function setViewerId(string $viewerId): DocumentAccess { + $this->viewerId = $viewerId; + + return $this; + } + + /** + * Get the viewer of the document. + * + * @since 15.0.0 + * + * @return string + */ + public function getViewerId(): string { + return $this->viewerId; + } + + + /** + * Set the list of users that have read access to the document. + * + * @since 15.0.0 + * + * @param array $users + * + * @return DocumentAccess + */ + public function setUsers(array $users): DocumentAccess { + $this->users = $users; + + return $this; + } + + /** + * Add an entry to the list of users that have read access to the document. + * + * @since 15.0.0 + * + * @param string $user + * + * @return DocumentAccess + */ + public function addUser(string $user): DocumentAccess { + $this->users[] = $user; + + return $this; + } + + /** + * Add multiple entries to the list of users that have read access to the + * document. + * + * @since 15.0.0 + * + * @param array $users + * + * @return DocumentAccess + */ + public function addUsers($users): DocumentAccess { + $this->users = array_merge($this->users, $users); + + return $this; + } + + /** + * Get the complete list of users that have read access to the document. + * + * @since 15.0.0 + * + * @return array + */ + public function getUsers(): array { + return $this->users; + } + + + /** + * Set the list of groups that have read access to the document. + * + * @since 15.0.0 + * + * @param array $groups + * + * @return DocumentAccess + */ + public function setGroups(array $groups): DocumentAccess { + $this->groups = $groups; + + return $this; + } + + /** + * Add an entry to the list of groups that have read access to the document. + * + * @since 15.0.0 + * + * @param string $group + * + * @return DocumentAccess + */ + public function addGroup(string $group): DocumentAccess { + $this->groups[] = $group; + + return $this; + } + + /** + * Add multiple entries to the list of groups that have read access to the + * document. + * + * @since 15.0.0 + * + * @param array $groups + * + * @return DocumentAccess + */ + public function addGroups(array $groups) { + $this->groups = array_merge($this->groups, $groups); + + return $this; + } + + /** + * Get the complete list of groups that have read access to the document. + * + * @since 15.0.0 + * + * @return array + */ + public function getGroups(): array { + return $this->groups; + } + + + /** + * Set the list of circles that have read access to the document. + * + * @since 15.0.0 + * + * @param array $circles + * + * @return DocumentAccess + */ + public function setCircles(array $circles): DocumentAccess { + $this->circles = $circles; + + return $this; + } + + /** + * Add an entry to the list of circles that have read access to the document. + * + * @since 15.0.0 + * + * @param string $circle + * + * @return DocumentAccess + */ + public function addCircle(string $circle): DocumentAccess { + $this->circles[] = $circle; + + return $this; + } + + /** + * Add multiple entries to the list of groups that have read access to the + * document. + * + * @since 15.0.0 + * + * @param array $circles + * + * @return DocumentAccess + */ + public function addCircles(array $circles): DocumentAccess { + $this->circles = array_merge($this->circles, $circles); + + return $this; + } + + /** + * Get the complete list of circles that have read access to the document. + * + * @since 15.0.0 + * + * @return array + */ + public function getCircles(): array { + return $this->circles; + } + + + /** + * Set the list of links that have read access to the document. + * + * @since 15.0.0 + * + * @param array $links + * + * @return DocumentAccess + */ + public function setLinks(array $links): DocumentAccess { + $this->links = $links; + + return $this; + } + + /** + * Get the list of links that have read access to the document. + * + * @since 15.0.0 + * + * @return array + */ + public function getLinks(): array { + return $this->links; + } + + + /** + * @since 15.0.0 + * + * @return array + */ + public function jsonSerialize(): array { + return [ + 'ownerId' => $this->getOwnerId(), + 'viewerId' => $this->getViewerId(), + 'users' => $this->getUsers(), + 'groups' => $this->getGroups(), + 'circles' => $this->getCircles(), + 'links' => $this->getLinks() + ]; + } +} + diff --git a/lib/public/FullTextSearch/Model/IIndex.php b/lib/public/FullTextSearch/Model/IIndex.php new file mode 100644 index 00000000000..adfdf34aee6 --- /dev/null +++ b/lib/public/FullTextSearch/Model/IIndex.php @@ -0,0 +1,292 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for extcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +/** + * Interface IIndex + * + * Index are generated by FullTextSearch to manage the status of a document + * regarding the date of the last index and the date of the last modification + * of the original document. + * + * The uniqueness of an IndexDocument is made by the Id of the Content Provider + * and the Id of the original document within the Content Provider. + * + * We will call original document the source from which the IndexDocument is + * generated. As an example, an original document can be a file, a mail, ... + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Model + */ +interface IIndex { + + + const INDEX_OK = 1; + const INDEX_IGNORE = 2; + + const INDEX_META = 4; + const INDEX_CONTENT = 8; + const INDEX_FULL = 12; + const INDEX_REMOVE = 16; + + const INDEX_DONE = 32; + const INDEX_FAILED = 64; + + const ERROR_FAILED = 1; + const ERROR_FAILED2 = 2; + const ERROR_FAILED3 = 4; + + const ERROR_SEV_1 = 1; + const ERROR_SEV_2 = 2; + const ERROR_SEV_3 = 3; + const ERROR_SEV_4 = 4; + + + /** + * Get the Id of the Content Provider. + * + * @since 15.0.0 + * + * @return string + */ + public function getProviderId(): string; + + + /** + * Get the Id of the original document. + * + * @since 15.0.0 + * + * @return string + */ + public function getDocumentId(): string; + + + /** + * Set the source of the original document. + * + * @since 15.0.0 + * + * @param string $source + * + * @return IIndex + */ + public function setSource(string $source): IIndex; + + /** + * Get the source of the original document. + * + * @since 15.0.0 + * + * @return string + */ + public function getSource(): string; + + + /** + * Set the owner of the original document. + * + * @since 15.0.0 + * + * @param string $ownerId + * + * @return IIndex + */ + public function setOwnerId(string $ownerId): IIndex; + + /** + * Get the owner of the original document. + * + * @since 15.0.0 + * + * @return string + */ + public function getOwnerId(): string; + + + /** + * Set the current index status (bit flag) of the original document. + * If $reset is true, the status is reset to the defined value. + * + * @since 15.0.0 + * + * @param int $status + * @param bool $reset + * + * @return IIndex + */ + public function setStatus(int $status, bool $reset = false): IIndex; + + /** + * Get the current index status of the original document. + * + * @since 15.0.0 + * + * @return int + */ + public function getStatus(): int; + + /** + * Check if the document fit a specific status. + * + * @since 15.0.0 + * + * @param int $status + * + * @return bool + */ + public function isStatus(int $status): bool; + + /** + * Remove a status. + * + * @since 15.0.0 + * + * @param int $status + * + * @return IIndex + */ + public function unsetStatus(int $status): IIndex; + + + /** + * Add an option related to the original document (as string). + * + * @since 15.0.0 + * + * @param string $option + * @param string|int $value + * + * @return IIndex + */ + public function addOption(string $option, string $value): IIndex; + + /** + * Add an option related to the original document (as integer). + * + * @since 15.0.0 + * + * @param string $option + * @param int $value + * + * @return IIndex + */ + public function addOptionInt(string $option, int $value): IIndex; + + /** + * Get the option related to the original document (as string). + * + * @since 15.0.0 + * + * @param string $option + * @param string $default + * + * @return string + */ + public function getOption(string $option, string $default = ''): string; + + /** + * Get the option related to the original document (as integer). + * + * @since 15.0.0 + * + * @param string $option + * @param int $default + * + * @return int + */ + public function getOptionInt(string $option, int $default = 0): int; + + /** + * Get all options related to the original document. + * + * @since 15.0.0 + * + * @return array + */ + public function getOptions(): array; + + + /** + * Add an error log related to the Index. + * + * @since 15.0.0 + * + * @param string $message + * @param string $exception + * @param int $sev + * + * @return IIndex + */ + public function addError(string $message, string $exception = '', int $sev = self::ERROR_SEV_3): IIndex; + + /** + * Returns the number of known errors related to the Index. + * + * @since 15.0.0 + * + * @return int + */ + public function getErrorCount(): int; + + /** + * Reset all error logs related to the Index. + * + * @since 15.0.0 + */ + public function resetErrors(): IIndex; + + + /** + * Set the date of the last index. + * + * @since 15.0.0 + * + * @param int $lastIndex + * + * @return IIndex + */ + public function setLastIndex(int $lastIndex = -1): IIndex; + + /** + * Get the date of the last index. + * + * @since 15.0.0 + * + * @return int + */ + public function getLastIndex(): int; + + +} + diff --git a/lib/public/FullTextSearch/Model/IIndexOptions.php b/lib/public/FullTextSearch/Model/IIndexOptions.php new file mode 100644 index 00000000000..8cc5da13d4d --- /dev/null +++ b/lib/public/FullTextSearch/Model/IIndexOptions.php @@ -0,0 +1,86 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +/** + * Interface IIndexOptions + * + * IndexOptions are created in FullTextSearch when an admin initiate an index + * from the command line: + * + * ./occ fulltextsearch:index "{\"option1\": \"value\", \"option2\": true}" + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Model + */ +interface IIndexOptions { + + + /** + * Get the value (as a string) for an option. + * + * @since 15.0.0 + * + * @param string $option + * @param string $default + * + * @return string + */ + public function getOption(string $option, string $default = ''): string; + + /** + * Get the value (as an array) for an option. + * + * @since 15.0.0 + * + * @param string $option + * @param array $default + * + * @return array + */ + public function getOptionArray(string $option, array $default = []): array; + + /** + * Get the value (as an boolean) for an option. + * + * @since 15.0.0 + * + * @param string $option + * @param bool $default + * + * @return bool + */ + public function getOptionBool(string $option, bool $default): bool; + +} + diff --git a/lib/public/FullTextSearch/Model/IRunner.php b/lib/public/FullTextSearch/Model/IRunner.php new file mode 100644 index 00000000000..0dff82bd5a0 --- /dev/null +++ b/lib/public/FullTextSearch/Model/IRunner.php @@ -0,0 +1,142 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +/** + * Interface IRunner + * + * The indexing process can be long and heavy, and because errors can + * be encountered the process is wrapped using this interface. + * It allows the any extension of FullTextSearch to communicate with the process. + * + * The IRunner is coming with some methods so the Search Platform can + * returns important information and errors to be displayed to the admin. + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Model + */ +interface IRunner { + + + const RESULT_TYPE_SUCCESS = 1; + const RESULT_TYPE_WARNING = 4; + const RESULT_TYPE_FAIL = 9; + + + /** + * Info are displayed in the user interface when an admin execute the + * ./occ fulltextsearch:index command. + * + * quick list of info that can be edited: + * 'documentId', 'info', 'title', 'resultIndex', 'resultStatus', + * 'content', 'documentCurrent', 'documentTotal', 'progressStatus', + * 'errorCurrent', 'errorException', 'errorIndex'. + * + * List of all editable info can be find in the Command\Index.php of the + * FullTextSearch app. + * (look for a comment 'full list of info that can be edited') + * + * @since 15.0.0 + * + * @param string $info + * @param string $value + */ + public function setInfo(string $info, string $value); + + + /** + * This method should be used when editing multiple info to avoid too many + * refresh of the interface. + * + * @since 15.0.0 + * + * @param array $data + */ + public function setInfoArray(array $data); + + + /** + * Method used to update the current Action when an index is running. + * + * This method should be used instead of manually update the 'action' using + * setInfo()/setInfoArray() as it is also used to keep the process alive, + * manage the input, and some statistics of the load of the process. + * + * $action is a string with no space + * $force should be set to true if the action is heavy while being executed + * multiple times + * + * @since 15.0.0 + * + * @param string $action + * @param bool $force + * + * @return string + * @throws \Exception + */ + public function updateAction(string $action = '', bool $force = false): string; + + + /** + * Call this method in a Search Platform or Content Provider if there is an + * issue while generating a document or while indexing the current document. + * This is used to store and display errors in the UI during an index to help + * admin to keep track of errors. + * + * @since 15.0.0 + * + * @param IIndex $index + * @param string $message + * @param string $class + * @param int $sev + */ + public function newIndexError(IIndex $index, string $message, string $class = '', int $sev = 3); + + + /** + * Call this method only in a Search Platform after an index of a document. + * This is used to store and display results (good or bad) in the UI during + * an index to help admin to keep track of fail and successful indexes. + * + * @since 15.0.0 + * + * @param IIndex $index + * @param string $message + * @param string $status + * @param int $type + */ + public function newIndexResult(IIndex $index, string $message, string $status, int $type); + + +} + diff --git a/lib/public/FullTextSearch/Model/ISearchRequest.php b/lib/public/FullTextSearch/Model/ISearchRequest.php new file mode 100644 index 00000000000..073b4805f63 --- /dev/null +++ b/lib/public/FullTextSearch/Model/ISearchRequest.php @@ -0,0 +1,326 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +/** + * Interface ISearchRequest + * + * When a search request is initiated, from a request from the front-end or using + * the IFullTextSearchManager::search() method, FullTextSearch will create a + * SearchRequest object, based on this interface. + * + * The object will be passed to the targeted Content Provider so it can convert + * search options using available method. + * + * The object is then encapsulated in a SearchResult and send to the + * Search Platform. + * + * @since 15.0.0 + * + * + * @package OCP\FullTextSearch\Model + */ +interface ISearchRequest { + + + /** + * Get the maximum number of results to be returns by the Search Platform. + * + * @since 15.0.0 + * + * @return int + */ + public function getSize(): int; + + + /** + * Get the current page. + * Used by pagination. + * + * @since 15.0.0 + * + * @return int + */ + public function getPage(): int; + + + /** + * Get the author of the request. + * + * @since 15.0.0 + * + * @return string + */ + public function getAuthor(): string; + + /** + * Get the searched string. + * + * @since 15.0.0 + * + * @return string + */ + public function getSearch(): string; + + + /** + * Get the value of an option (as string). + * + * @since 15.0.0 + * + * @param string $option + * @param string $default + * + * @return string + */ + public function getOption(string $option, string $default = ''): string; + + /** + * Get the value of an option (as array). + * + * @since 15.0.0 + * + * @param string $option + * @param array $default + * + * @return array + */ + public function getOptionArray(string $option, array $default = []): array; + + + /** + * Limit the search to a part of the document. + * + * @since 15.0.0 + * + * @param string $part + * + * @return ISearchRequest + */ + public function addPart(string $part): ISearchRequest; + + /** + * Limit the search to an array of parts of the document. + * + * @since 15.0.0 + * + * @param array $parts + * + * @return ISearchRequest + */ + public function setParts(array $parts): ISearchRequest; + + /** + * Get the parts the search is limited to. + * + * @since 15.0.0 + * + * @return array + */ + public function getParts(): array; + + + /** + * Limit the search to a specific meta tag. + * + * @since 15.0.0 + * + * @param string $tag + * + * @return ISearchRequest + */ + public function addMetaTag(string $tag): ISearchRequest; + + /** + * Get the meta tags the search is limited to. + * + * @since 15.0.0 + * + * @return array + */ + public function getMetaTags(): array; + + /** + * Limit the search to an array of meta tags. + * + * @since 15.0.0 + * + * @param array $tags + * + * @return ISearchRequest + */ + public function setMetaTags(array $tags): IsearchRequest; + + + /** + * Limit the search to a specific sub tag. + * + * @since 15.0.0 + * + * @param string $source + * @param string $tag + * + * @return ISearchRequest + */ + public function addSubTag(string $source, string $tag): ISearchRequest; + + /** + * Get the sub tags the search is limited to. + * + * @since 15.0.0 + * + * @param bool $formatted + * + * @return array + */ + public function getSubTags(bool $formatted): array; + + /** + * Limit the search to an array of sub tags. + * + * @since 15.0.0 + * + * @param array $tags + * + * @return ISearchRequest + */ + public function setSubTags(array $tags): ISearchRequest; + + + /** + * Limit the search to a specific field of the mapping, using a full string. + * + * @since 15.0.0 + * + * @param string $field + * + * @return ISearchRequest + */ + public function addLimitField(string $field): ISearchRequest; + + /** + * Get the fields the search is limited to. + * + * @since 15.0.0 + * + * @return array + */ + public function getLimitFields(): array; + + + /** + * Limit the search to a specific field of the mapping, using a wildcard on + * the search string. + * + * @since 15.0.0 + * + * @param string $field + * + * @return ISearchRequest + */ + public function addWildcardField(string $field): ISearchRequest; + + /** + * Get the limit to field of the mapping. + * + * @since 15.0.0 + * + * @return array + */ + public function getWildcardFields(): array; + + + /** + * Filter the results, based on a group of field, using regex + * + * @since 15.0.0 + * + * @param array $filters + * + * @return ISearchRequest + */ + public function addRegexFilters(array $filters): ISearchRequest; + + /** + * Get the regex filters the search is limit to. + * + * @since 15.0.0 + * + * @return array + */ + public function getRegexFilters(): array; + + + /** + * Filter the results, based on a group of field, using wildcard + * + * @since 15.0.0 + * + * @param array $filter + * + * @return ISearchRequest + */ + public function addWildcardFilter(array $filter): ISearchRequest; + + /** + * Get the wildcard filters the search is limit to. + * + * @since 15.0.0 + * + * @return array + */ + public function getWildcardFilters(): array; + + + /** + * Add an extra field to the search. + * + * @since 15.0.0 + * + * @param string $field + * + * @return ISearchRequest + */ + public function addField(string $field): ISearchRequest; + + /** + * Get the list of extra field to search into. + * + * @since 15.0.0 + * + * @return array + */ + public function getFields(): array; + + +} + diff --git a/lib/public/FullTextSearch/Model/ISearchResult.php b/lib/public/FullTextSearch/Model/ISearchResult.php new file mode 100644 index 00000000000..a7dcba82f5c --- /dev/null +++ b/lib/public/FullTextSearch/Model/ISearchResult.php @@ -0,0 +1,198 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +use OCP\FullTextSearch\IFullTextSearchProvider; + + +/** + * Interface ISearchResult + * + * When a search request is initiated, FullTextSearch will create a SearchResult + * object, based on this interface, containing the SearchRequest and the targeted + * Content Provider. + * + * The object will be passed to the Search Platform, which will proceed to the + * search and fill the SearchResult object with results. + * + * Then, the object will be passed to the targeted Content Provider that will + * improve the Search Results with detailed informations. + * + * Finally, the SearchResult is returned to the original search request. + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Model + */ +interface ISearchResult { + + + /** + * Get the original SearchRequest. + * + * @see ISearchRequest + * + * @since 15.0.0 + * + * @return ISearchRequest + */ + public function getRequest(): ISearchRequest; + + /** + * Get the targeted Content Provider. + * + * @since 15.0.0 + * + * @return IFullTextSearchProvider + */ + public function getProvider(): IFullTextSearchProvider; + + + /** + * Add an IndexDocument as one of the result of the search request. + * + * @since 15.0.0 + * + * @param IndexDocument $document + * + * @return ISearchResult + */ + public function addDocument(IndexDocument $document): ISearchResult; + + /** + * Returns all result of the search request, in an array of IndexDocument. + * + * @since 15.0.0 + * + * @return array + */ + public function getDocuments(): array; + + /** + * Set an array of IndexDocument as the result of the search request. + * + * @since 15.0.0 + * + * @param IndexDocument[] $documents + * + * @return ISearchResult + */ + public function setDocuments(array $documents): ISearchResult; + + + /** + * Add an aggregation to the result. + * + * @since 15.0.0 + * + * @param string $category + * @param string $value + * @param int $count + * + * @return ISearchResult + */ + public function addAggregation(string $category, string $value, int $count): ISearchResult; + + /** + * Get all aggregations. + * + * @since 15.0.0 + * + * @param string $category + * + * @return array + */ + public function getAggregations(string $category): array; + + + /** + * Set the raw result of the request. + * + * @since 15.0.0 + * + * @param string $result + * + * @return ISearchResult + */ + public function setRawResult(string $result): ISearchResult; + + + /** + * Set the total number of results for the search request. + * Used by pagination. + * + * @since 15.0.0 + * + * @param int $total + * + * @return ISearchResult + */ + public function setTotal(int $total): ISearchResult; + + + /** + * Set the top score for the search request. + * + * @since 15.0.0 + * + * @param int $score + * + * @return ISearchResult + */ + public function setMaxScore(int $score): ISearchResult; + + + /** + * Set the time spent by the request to perform the search. + * + * @since 15.0.0 + * + * @param int $time + * + * @return ISearchResult + */ + public function setTime(int $time): ISearchResult; + + + /** + * Set to true if the request timed out. + * + * @since 15.0.0 + * + * @param bool $timedOut + * + * @return ISearchResult + */ + public function setTimedOut(bool $timedOut): ISearchResult; + +} + diff --git a/lib/public/FullTextSearch/Model/IndexDocument.php b/lib/public/FullTextSearch/Model/IndexDocument.php new file mode 100644 index 00000000000..78679ac6225 --- /dev/null +++ b/lib/public/FullTextSearch/Model/IndexDocument.php @@ -0,0 +1,974 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +use JsonSerializable; + +/** + * Class IndexDocument + * + * This is one of the main class of the FullTextSearch, used as a data transfer + * object. An IndexDocument is created to manage documents around FullTextSearch, + * during an index and during a search. + * The uniqueness of an IndexDocument is made by the Id of the Content Provider + * and the Id of the original document within the Content Provider. + * + * We will call original document the source from which the IndexDocument is + * generated. As an example, an original document can be a file, a mail, ... + * + * @since 15.0.0 + * + * @package OC\FullTextSearch\Model + */ +class IndexDocument implements JsonSerializable { + + + const NOT_ENCODED = 0; + const ENCODED_BASE64 = 1; + + + /** @var string */ + protected $id = ''; + + /** @var string */ + protected $providerId = ''; + + /** @var DocumentAccess */ + protected $access; + + /** @var IIndex */ + protected $index; + + /** @var int */ + protected $modifiedTime = 0; + + /** @var string */ + protected $source = ''; + + /** @var array */ + protected $tags = []; + + /** @var array */ + protected $metaTags = []; + + /** @var array */ + protected $subTags = []; + + /** @var string */ + protected $title = ''; + + /** @var string */ + protected $content = ''; + + /** @var string */ + protected $hash = ''; + + /** @var array */ + protected $parts = []; + + /** @var string */ + protected $link = ''; + + /** @var array */ + protected $more = []; + + /** @var array */ + protected $excerpts = []; + + /** @var string */ + protected $score = ''; + + /** @var array */ + protected $info = []; + + /** @var int */ + protected $contentEncoded = 0; + + + /** + * IndexDocument constructor. + * + * On creation, we assure the uniqueness of the object using the providerId + * and the Id of the original document. + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + */ + public function __construct(string $providerId, string $documentId) { + $this->providerId = $providerId; + $this->id = $documentId; + } + + + /** + * Returns the Id of the original document. + * + * @since 15.0.0 + * + * @return string + */ + final public function getId(): string { + return $this->id; + } + + + /** + * Returns the Id of the provider. + * + * @since 15.0.0 + * + * @return string + */ + final public function getProviderId(): string { + return $this->providerId; + } + + + /** + * Set the Index related to the IndexDocument. + * + * @see IIndex + * + * @since 15.0.0 + * + * @param IIndex $index + * + * @return IndexDocument + */ + final public function setIndex(IIndex $index): IndexDocument { + $this->index = $index; + + return $this; + } + + /** + * Get the Index. + * + * @since 15.0.0 + * + * @return IIndex + */ + final public function getIndex(): IIndex { + return $this->index; + } + + + /** + * Set the modified time of the original document. + * + * @since 15.0.0 + * + * @param int $modifiedTime + * + * @return IndexDocument + */ + final public function setModifiedTime(int $modifiedTime): IndexDocument { + $this->modifiedTime = $modifiedTime; + + return $this; + } + + /** + * Get the modified time of the original document. + * + * @since 15.0.0 + * + * @return int + */ + final public function getModifiedTime(): int { + return $this->modifiedTime; + } + + /** + * Check if the original document of the IndexDocument is older than $time. + * + * @since 15.0.0 + * + * @param int $time + * + * @return bool + */ + final public function isOlderThan(int $time): bool { + return ($this->modifiedTime < $time); + } + + + /** + * Set the read rights of the original document using a DocumentAccess. + * + * @see DocumentAccess + * + * @since 15.0.0 + * + * @param DocumentAccess $access + * + * @return $this + */ + final public function setAccess(DocumentAccess $access) { + $this->access = $access; + + return $this; + } + + /** + * Get the DocumentAccess related to the original document. + * + * @since 15.0.0 + * + * @return DocumentAccess + */ + final public function getAccess(): DocumentAccess { + return $this->access; + } + + + /** + * Add a tag to the list. + * + * @since 15.0.0 + * + * @param string $tag + * + * @return IndexDocument + */ + final public function addTag(string $tag): IndexDocument { + $this->tags[] = $tag; + + return $this; + } + + /** + * Set the list of tags assigned to the original document. + * + * @since 15.0.0 + * + * @param array $tags + * + * @return IndexDocument + */ + final public function setTags(array $tags): IndexDocument { + $this->tags = $tags; + + return $this; + } + + /** + * Get the list of tags assigned to the original document. + * + * @since 15.0.0 + * + * @return array + */ + final public function getTags(): array { + return $this->tags; + } + + + /** + * Add a meta tag to the list. + * + * @since 15.0.0 + * + * @param string $tag + * + * @return IndexDocument + */ + final public function addMetaTag(string $tag): IndexDocument { + $this->metaTags[] = $tag; + + return $this; + } + + /** + * Set the list of meta tags assigned to the original document. + * + * @since 15.0.0 + * + * @param array $tags + * + * @return IndexDocument + */ + final public function setMetaTags(array $tags): IndexDocument { + $this->metaTags = $tags; + + return $this; + } + + /** + * Get the list of meta tags assigned to the original document. + * + * @since 15.0.0 + * + * @return array + */ + final public function getMetaTags(): array { + return $this->metaTags; + } + + + /** + * Add a sub tag to the list. + * + * @since 15.0.0 + * + * @param string $sub + * @param string $tag + * + * @return IndexDocument + */ + final public function addSubTag(string $sub, string $tag): IndexDocument { + $this->subTags[$sub] = $tag; + + return $this; + } + + /** + * Set the list of sub tags assigned to the original document. + * + * @since 15.0.0 + * + * @param array $tags + * + * @return IndexDocument + */ + final public function setSubTags(array $tags): IndexDocument { + $this->subTags = $tags; + + return $this; + } + + /** + * Get the list of sub tags assigned to the original document. + * If $formatted is true, the result will be formatted in a one + * dimensional array. + * + * @since 15.0.0 + * + * @param bool $formatted + * + * @return array + */ + final public function getSubTags(bool $formatted = false): array { + if ($formatted === false) { + return $this->subTags; + } + + $subTags = []; + $ak = array_keys($this->subTags); + foreach ($ak as $source) { + $tags = $this->subTags[$source]; + foreach ($tags as $tag) { + $subTags[] = $source . '_' . $tag; + } + } + + return $subTags; + } + + + /** + * Set the source of the original document. + * + * @since 15.0.0 + * + * @param string $source + * + * @return IndexDocument + */ + final public function setSource(string $source): IndexDocument { + $this->source = $source; + + return $this; + } + + /** + * Get the source of the original document. + * + * @since 15.0.0 + * + * @return string + */ + final public function getSource(): string { + return $this->source; + } + + + /** + * Set the title of the original document. + * + * @since 15.0.0 + * + * @param string $title + * + * @return IndexDocument + */ + final public function setTitle(string $title): IndexDocument { + $this->title = $title; + + return $this; + } + + /** + * Get the title of the original document. + * + * @since 15.0.0 + * + * @return string + */ + final public function getTitle(): string { + return $this->title; + } + + + /** + * Set the content of the document. + * $encoded can be NOT_ENCODED or ENCODED_BASE64 if the content is raw or + * encoded in base64. + * + * @since 15.0.0 + * + * @param string $content + * @param int $encoded + * + * @return IndexDocument + */ + final public function setContent(string $content, int $encoded = 0): IndexDocument { + $this->content = $content; + $this->contentEncoded = $encoded; + + return $this; + } + + /** + * Get the content of the original document. + * + * @since 15.0.0 + * + * @return string + */ + final public function getContent(): string { + return $this->content; + } + + /** + * Returns the type of the encoding on the content. + * + * @since 15.0.0 + * + * @return int + */ + final public function isContentEncoded(): int { + return $this->contentEncoded; + } + + /** + * Return the size of the content. + * + * @since 15.0.0 + * + * @return int + */ + final public function getContentSize(): int { + return strlen($this->getContent()); + } + + + /** + * Generate an hash, based on the content of the original document. + * + * @since 15.0.0 + * + * @return IndexDocument + */ + final public function initHash(): IndexDocument { + if ($this->getContent() === '' || is_null($this->getContent())) { + return $this; + } + + $this->hash = hash("md5", $this->getContent()); + + return $this; + } + + /** + * Set the hash of the original document. + * + * @since 15.0.0 + * + * @param string $hash + * + * @return IndexDocument + */ + final public function setHash(string $hash): IndexDocument { + $this->hash = $hash; + + return $this; + } + + /** + * Get the hash of the original document. + * + * @since 15.0.0 + * + * @return string + */ + final public function getHash(): string { + return $this->hash; + } + + + /** + * Add a part, identified by a string, and its content. + * + * It is strongly advised to use alphanumerical chars with no space in the + * $part string. + * + * @since 15.0.0 + * + * @param string $part + * @param string $content + * + * @return IndexDocument + */ + final public function addPart(string $part, string $content): IndexDocument { + $this->parts[$part] = $content; + + return $this; + } + + /** + * Set all parts and their content. + * + * @since 15.0.0 + * + * @param array $parts + * + * @return IndexDocument + */ + final public function setParts(array $parts): IndexDocument { + $this->parts = $parts; + + return $this; + } + + /** + * Get all parts of the IndexDocument. + * + * @since 15.0.0 + * + * @return array + */ + final public function getParts(): array { + return $this->parts; + } + + + /** + * Add a link, usable by the frontend. + * + * @since 15.0.0 + * + * @param string $link + * + * @return IndexDocument + */ + final public function setLink(string $link): IndexDocument { + $this->link = $link; + + return $this; + } + + /** + * Get the link. + * + * @since 15.0.0 + * + * @return string + */ + final public function getLink(): string { + return $this->link; + } + + + /** + * Set more information that couldn't be set using other method. + * + * @since 15.0.0 + * + * @param array $more + * + * @return IndexDocument + */ + final public function setMore(array $more): IndexDocument { + $this->more = $more; + + return $this; + } + + /** + * Get more information. + * + * @since 15.0.0 + * + * @return array + */ + final public function getMore(): array { + return $this->more; + } + + + /** + * Add some excerpt of the content of the original document, usually based + * on the search request. + * + * @since 15.0.0 + * + * @param string $excerpt + * + * @return IndexDocument + */ + final public function addExcerpt(string $excerpt): IndexDocument { + $excerpt = $this->cleanExcerpt($excerpt); + + $this->excerpts[] = $excerpt; + + return $this; + } + + /** + * Set all excerpts of the content of the original document. + * + * @since 15.0.0 + * + * @param array $excerpts + * + * @return IndexDocument + */ + final public function setExcerpts(array $excerpts): IndexDocument { + $excerpts = array_map([$this, 'cleanExcerpt'], $excerpts); + + $this->excerpts = $excerpts; + + return $this; + } + + /** + * Get all excerpts of the content of the original document. + * + * @since 15.0.0 + * + * @return array + */ + final public function getExcerpts(): array { + return $this->excerpts; + } + + /** + * Clean excerpt. + * + * @since 15.0.0 + * + * @param string $excerpt + * + * @return string + */ + final public function cleanExcerpt(string $excerpt): string { + $excerpt = str_replace("\\n", ' ', $excerpt); + $excerpt = str_replace("\\r", ' ', $excerpt); + $excerpt = str_replace("\\t", ' ', $excerpt); + $excerpt = str_replace("\n", ' ', $excerpt); + $excerpt = str_replace("\r", ' ', $excerpt); + $excerpt = str_replace("\t", ' ', $excerpt); + + return $excerpt; + } + + /** + * Set the score to the result assigned to this document during a search + * request. + * + * @since 15.0.0 + * + * @param string $score + * + * @return IndexDocument + */ + final public function setScore(string $score): IndexDocument { + $this->score = $score; + + return $this; + } + + /** + * Get the score. + * + * @since 15.0.0 + * + * @return string + */ + final public function getScore(): string { + return $this->score; + } + + + /** + * Set some information about the original document that will be available + * to the front-end when displaying search result. (as string) + * Because this information will not be indexed, this method can also be + * used to manage some data while filling the IndexDocument before its + * indexing. + * + * @since 15.0.0 + * + * @param string $info + * @param string $value + * + * @return IndexDocument + */ + final public function setInfo(string $info, string $value): IndexDocument { + $this->info[$info] = $value; + + return $this; + } + + /** + * Get an information about a document. (string) + * + * @since 15.0.0 + * + * @param string $info + * @param string $default + * + * @return string + */ + final public function getInfo(string $info, string $default = ''): string { + if (!key_exists($info, $this->info)) { + return $default; + } + + return $this->info[$info]; + } + + /** + * Set some information about the original document that will be available + * to the front-end when displaying search result. (as array) + * Because this information will not be indexed, this method can also be + * used to manage some data while filling the IndexDocument before its + * indexing. + * + * @since 15.0.0 + * + * @param string $info + * @param array $value + * + * @return IndexDocument + */ + final public function setInfoArray(string $info, array $value): IndexDocument { + $this->info[$info] = $value; + + return $this; + } + + /** + * Get an information about a document. (array) + * + * @since 15.0.0 + * + * @param string $info + * @param array $default + * + * @return array + */ + final public function getInfoArray(string $info, array $default = []): array { + if (!key_exists($info, $this->info)) { + return $default; + } + + return $this->info[$info]; + } + + /** + * Set some information about the original document that will be available + * to the front-end when displaying search result. (as int) + * Because this information will not be indexed, this method can also be + * used to manage some data while filling the IndexDocument before its + * indexing. + * + * @since 15.0.0 + * + * @param string $info + * @param int $value + * + * @return IndexDocument + */ + final public function setInfoInt(string $info, int $value): IndexDocument { + $this->info[$info] = $value; + + return $this; + } + + /** + * Get an information about a document. (int) + * + * @since 15.0.0 + * + * @param string $info + * @param int $default + * + * @return int + */ + final public function getInfoInt(string $info, int $default = 0): int { + if (!key_exists($info, $this->info)) { + return $default; + } + + return $this->info[$info]; + } + + /** + * Set some information about the original document that will be available + * to the front-end when displaying search result. (as bool) + * Because this information will not be indexed, this method can also be + * used to manage some data while filling the IndexDocument before its + * indexing. + * + * @since 15.0.0 + * + * @param string $info + * @param bool $value + * + * @return IndexDocument + */ + final public function setInfoBool(string $info, bool $value): IndexDocument { + $this->info[$info] = $value; + + return $this; + } + + /** + * Get an information about a document. (bool) + * + * @since 15.0.0 + * + * @param string $info + * @param bool $default + * + * @return bool + */ + final public function getInfoBool(string $info, bool $default = false): bool { + if (!key_exists($info, $this->info)) { + return $default; + } + + return $this->info[$info]; + } + + /** + * Get all info. + * + * @since 15.0.0 + * + * @return array + */ + final public function getInfoAll(): array { + + $info = []; + foreach ($this->info as $k => $v) { + if (substr($k, 0, 1) === '_') { + continue; + } + + $info[$k] = $v; + } + + return $info; + } + + + /** + * @since 15.0.0 + * + * On some version of PHP, it is better to force destruct the object. + * And during the index, the number of generated IndexDocument can be + * _huge_. + */ + public function __destruct() { + unset($this->id); + unset($this->providerId); + unset($this->access); + unset($this->modifiedTime); + unset($this->title); + unset($this->content); + unset($this->hash); + unset($this->link); + unset($this->source); + unset($this->tags); + unset($this->metaTags); + unset($this->subTags); + unset($this->more); + unset($this->excerpts); + unset($this->score); + unset($this->info); + unset($this->contentEncoded); + } + + /** + * @since 15.0.0 + * + * @return array + */ + public function jsonSerialize() { + return [ + 'id' => $this->getId(), + 'providerId' => $this->getProviderId(), + 'access' => $this->access, + 'modifiedTime' => $this->getModifiedTime(), + 'title' => $this->getTitle(), + 'link' => $this->getLink(), + 'index' => $this->index, + 'source' => $this->getSource(), + 'info' => $this->getInfoAll(), + 'hash' => $this->getHash(), + 'contentSize' => $this->getContentSize(), + 'tags' => $this->getTags(), + 'metatags' => $this->getMetaTags(), + 'subtags' => $this->getSubTags(), + 'more' => $this->getMore(), + 'excerpts' => $this->getExcerpts(), + 'score' => $this->getScore() + ]; + } + +} + diff --git a/lib/public/FullTextSearch/Model/SearchOption.php b/lib/public/FullTextSearch/Model/SearchOption.php new file mode 100644 index 00000000000..ae6ad3241b6 --- /dev/null +++ b/lib/public/FullTextSearch/Model/SearchOption.php @@ -0,0 +1,296 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +use JsonSerializable; + + +/** + * @since 15.0.0 + * + * Class SearchOption + * + * @package OCP\FullTextSearch\Model + */ +final class SearchOption implements JsonSerializable { + + + const CHECKBOX = 'checkbox'; + const INPUT = 'input'; + + const INPUT_SMALL = 'small'; + + + /** @var string */ + private $name = ''; + + /** @var string */ + private $title = ''; + + /** @var string */ + private $type = ''; + + /** @var string */ + private $size = ''; + + /** @var string */ + private $placeholder = ''; + + + /** + * * + * + * The array can be empty in case no search options are available. + * The format of the array must be like this: + * + * [ + * 'panel' => [ + * 'options' => [ + * OPTION1, + * OPTION2, + * OPTION3 + * ] + * ], + * 'navigation' => [ + * 'icon' => 'css-class-of-the-icon', + * 'options' => [ + * OPTION1, + * OPTION2, + * OPTION3 + * ] + * ] + * ] + * + * - PANEL contains entries that will be displayed in the app itself, when + * a search is initiated. + * - NAVIGATION contains entries that will be available when using the + * FullTextSearch navigation page + * - OPTION is an element that define each option available to the user. + * + * The format for the options must be like this: + * + * [ + * 'name' => 'name_of_the_option', + * 'title' => 'Name displayed in the panel', + * 'type' => '', + * 'size' => '' (optional), + * 'placeholder' => '' (optional) + * ] + * + * - NAME is the variable name that is sent to the IFullTextSearchProvider + * when a ISearchRequest is requested. (keys in the array returned by the + * ISearchRequest->getOptions()) + * - TYPE can be 'input' or 'checkbox' + * - SIZE is only used in case TYPE='input', default is 'large' but can be + * 'small' + * - PLACEHOLDER is only used in case TYPE='input', default is empty. + */ + + /** + * SearchOption constructor. + * + * Some value can be setduring the creation of the object. + * + * @since 15.0.0 + * + * @param string $name + * @param string $title + * @param string $type + * @param string $size + * @param string $placeholder + */ + public function __construct(string $name = '', string $title = '', string $type = '', string $size = '', string $placeholder = '') { + $this->name = $name; + $this->title = $title; + $this->type = $type; + $this->size = $size; + $this->placeholder = $placeholder; + } + + + /** + * Set the name/key of the option. + * The string should only contains alphanumerical chars and underscore. + * The key can be retrieve when using ISearchRequest::getOption + * + * @see ISearchRequest::getOption + * + * @since 15.0.0 + * + * @param string $name + * + * @return SearchOption + */ + public function setName(string $name): SearchOption { + $this->name = $name; + + return $this; + } + + /** + * Get the name/key of the option. + * + * @since 15.0.0 + * + * @return string + */ + public function getName(): string { + return $this->name; + } + + + /** + * Set the title/display name of the option. + * + * @since 15.0.0 + * + * @param string $title + * + * @return SearchOption + */ + public function setTitle(string $title): SearchOption { + $this->title = $title; + + return $this; + } + + /** + * Get the title of the option. + * + * @since 15.0.0 + * + * @return string + */ + public function getTitle(): string { + return $this->title; + } + + + /** + * Set the type of the option. + * $type can be SearchOption::CHECKBOX or SearchOption::INPUT + * + * @since 15.0.0 + * + * @param string $type + * + * @return SearchOption + */ + public function setType(string $type): SearchOption { + $this->type = $type; + + return $this; + } + + /** + * Get the type of the option. + * + * @since 15.0.0 + * + * @return string + */ + public function getType(): string { + return $this->type; + } + + + /** + * In case of Type is INPUT, set the size of the input field. + * Value can be SearchOption::INPUT_SMALL or not defined. + * + * @since 15.0.0 + * + * @param string $size + * + * @return SearchOption + */ + public function setSize(string $size): SearchOption { + $this->size = $size; + + return $this; + } + + /** + * Get the size of the INPUT. + * + * @since 15.0.0 + * + * @return string + */ + public function getSize(): string { + return $this->size; + } + + + /** + * In case of Type is , set the placeholder to be displayed in the input + * field. + * + * @since 15.0.0 + * + * @param string $placeholder + * + * @return SearchOption + */ + public function setPlaceholder(string $placeholder): SearchOption { + $this->placeholder = $placeholder; + + return $this; + } + + /** + * Get the placeholder. + * + * @since 15.0.0 + * + * @return string + */ + public function getPlaceholder(): string { + return $this->placeholder; + } + + + /** + * @since 15.0.0 + * + * @return array + */ + public function jsonSerialize(): array { + return [ + 'name' => $this->getName(), + 'title' => $this->getTitle(), + 'type' => $this->getType(), + 'size' => $this->getSize(), + 'placeholder' => $this->getPlaceholder() + ]; + } +} diff --git a/lib/public/FullTextSearch/Model/SearchTemplate.php b/lib/public/FullTextSearch/Model/SearchTemplate.php new file mode 100644 index 00000000000..7d9159190ea --- /dev/null +++ b/lib/public/FullTextSearch/Model/SearchTemplate.php @@ -0,0 +1,258 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018 + * @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 OCP\FullTextSearch\Model; + + +use JsonSerializable; +use OCP\FullTextSearch\IFullTextSearchProvider; + + +/** + * Class SearchTemplate + * + * This is a data transfer object that should be created by Content Provider + * when the getSearchTemplate() method is called. + * + * The object will contain templates to be displayed, and the list of the different + * options to be available to the user when he start a new search. + * + * The display of the Options is generated by the FullTextSearch app and Options + * can be displayed in 2 places: + * + * - the navigation page of the app that generate the indexed content. + * (files, bookmarks, deck, mails, ...) + * - the navigation page of the FullTextSearch app. + * + * Both pages will have different Options, and only the first one can integrate + * a specific template. + * + * @see IFullTextSearchProvider::getSearchTemplate + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Model + */ +final class SearchTemplate implements JsonSerializable { + + + /** @var string */ + private $icon = ''; + + /** @var string */ + private $css = ''; + + /** @var string */ + private $template = ''; + + /** @var SearchOption[] */ + private $panelOptions = []; + + /** @var SearchOption[] */ + private $navigationOptions = []; + + + /** + * SearchTemplate constructor. + * + * the class of the icon and the css file to be loaded can be set during the + * creation of the object. + * + * @since 15.0.0 + * + * @param string $icon + * @param string $css + */ + public function __construct(string $icon = '', string $css = '') { + $this->icon = $icon; + $this->css = $css; + } + + + /** + * Set the class of the icon to be displayed in the left panel of the + * FullTextSearch navigation page, in front of the related Content Provider. + * + * @since 15.0.0 + * + * @param string $class + * + * @return SearchTemplate + */ + public function setIcon(string $class): SearchTemplate { + $this->icon = $class; + + return $this; + } + + /** + * Get the class of the icon. + * + * @since 15.0.0 + * + * @return string + */ + public function getIcon(): string { + return $this->icon; + } + + + /** + * Set the path of a CSS file that will be loaded when needed. + * + * @since 15.0.0 + * + * @param string $css + * + * @return SearchTemplate + */ + public function setCss(string $css): SearchTemplate { + $this->css = $css; + + return $this; + } + + /** + * Get the path of the CSS file. + * + * @since 15.0.0 + * + * @return string + */ + public function getCss(): string { + return $this->css; + } + + + /** + * Set the path of the file of a template that the HTML will be displayed + * below the Options. + * This should only be used if your Content Provider needs to set options in + * a way not generated by FullTextSearch + * + * @since 15.0.0 + * + * @param string $template + * + * @return SearchTemplate + */ + public function setTemplate(string $template): SearchTemplate { + $this->template = $template; + + return $this; + } + + /** + * Get the path of the template file. + * + * @since 15.0.0 + * + * @return string + */ + public function getTemplate(): string { + return $this->template; + } + + + /** + * Add an option in the Panel that is displayed when the user start a search + * within the app that generate the content. + * + * @see SearchOption + * + * @since 15.0.0 + * + * @param SearchOption $option + * + * @return SearchTemplate + */ + public function addPanelOption(SearchOption $option): SearchTemplate { + $this->panelOptions[] = $option; + + return $this; + } + + /** + * Get all options to be displayed in the Panel. + * + * @since 15.0.0 + * + * @return SearchOption[] + */ + public function getPanelOptions(): array { + return $this->panelOptions; + } + + + /** + * Add an option in the left panel of the FullTextSearch navigation page. + * + * @see SearchOption + * + * @since 15.0.0 + * + * @param SearchOption $option + * + * @return SearchTemplate + */ + public function addNavigationOption(SearchOption $option): SearchTemplate { + $this->navigationOptions[] = $option; + + return $this; + } + + /** + * Get all options to be displayed in the FullTextSearch navigation page. + * + * @since 15.0.0 + * + * @return array + */ + public function getNavigationOptions(): array { + return $this->navigationOptions; + } + + + /** + * @since 15.0.0 + * + * @return array + */ + public function jsonSerialize(): array { + return [ + 'icon' => $this->getIcon(), + 'css' => $this->getCss(), + 'template' => $this->getTemplate(), + 'panel' => $this->getPanelOptions(), + 'navigation' => $this->getNavigationOptions() + ]; + } +} + diff --git a/lib/public/FullTextSearch/Service/IIndexService.php b/lib/public/FullTextSearch/Service/IIndexService.php new file mode 100644 index 00000000000..c5d1b9b3bcf --- /dev/null +++ b/lib/public/FullTextSearch/Service/IIndexService.php @@ -0,0 +1,99 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 OCP\FullTextSearch\Service; + + +use OCP\FullTextSearch\Model\IIndex; + + +/** + * Interface IIndexService + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Service + */ +interface IIndexService { + + + /** + * Retrieve an Index from the database, based on the Id of the Provider + * and the Id of the Document + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + * + * @return IIndex + */ + public function getIndex(string $providerId, string $documentId): IIndex; + + + /** + * Update the status of an Index. status is a bit flag, setting $reset to + * true will reset the status to the value defined in the parameter. + * + * @since 15.0.0 + * + * @param string $providerId + * @param string $documentId + * @param int $status + * @param bool $reset + */ + public function updateIndexStatus(string $providerId, string $documentId, int $status, bool $reset = false); + + + /** + * Update the status of an array of Index. status is a bit flag, setting $reset to + * true will reset the status to the value defined in the parameter. + * + * @since 15.0.0 + * + * @param string $providerId + * @param array $documentIds + * @param int $status + * @param bool $reset + */ + public function updateIndexesStatus(string $providerId, array $documentIds, int $status, bool $reset = false); + + + /** + * Update an array of Index. + * + * @since 15.0.0 + * + * @param array $indexes + */ + public function updateIndexes(array $indexes); + +} + diff --git a/lib/public/FullTextSearch/Service/IProviderService.php b/lib/public/FullTextSearch/Service/IProviderService.php new file mode 100644 index 00000000000..64153c13965 --- /dev/null +++ b/lib/public/FullTextSearch/Service/IProviderService.php @@ -0,0 +1,65 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 OCP\FullTextSearch\Service; + + +/** + * Interface IProviderService + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Service + */ +interface IProviderService { + + + /** + * Check if the provider $providerId is already indexed. + * + * @since 15.0.0 + * + * @param string $providerId + * + * @return bool + */ + public function isProviderIndexed(string $providerId); + + + /** + * Add the Javascript API in the navigation page of an app. + * + * @since 15.0.0 + */ + public function addJavascriptAPI(); + + +} + diff --git a/lib/public/FullTextSearch/Service/ISearchService.php b/lib/public/FullTextSearch/Service/ISearchService.php new file mode 100644 index 00000000000..7da38e44f5c --- /dev/null +++ b/lib/public/FullTextSearch/Service/ISearchService.php @@ -0,0 +1,89 @@ +<?php +declare(strict_types=1); + + +/** + * FullTextSearch - Full text search framework for Nextcloud + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 OCP\FullTextSearch\Service; + + +use OCP\FullTextSearch\Model\ISearchRequest; +use OCP\FullTextSearch\Model\ISearchResult; + + +/** + * Interface ISearchService + * + * @since 15.0.0 + * + * @package OCP\FullTextSearch\Service + */ +interface ISearchService { + + + /** + * generate a search request, based on an array: + * + * $request = + * [ + * 'providers' => (string/array) 'all' + * 'author' => (string) owner of the document. + * 'search' => (string) search string, + * 'size' => (int) number of items to be return + * 'page' => (int) page + * 'parts' => (array) parts of document to search within, + * 'options' = (array) search options, + * 'tags' => (array) tags, + * 'metatags' => (array) metatags, + * 'subtags' => (array) subtags + * ] + * + * 'providers' can be an array of providerIds + * + * @since 15.0.0 + * + * @param array $request + * + * @return ISearchRequest + */ + public function generateSearchRequest(array $request): ISearchRequest; + + + /** + * Search documents + * + * @since 15.0.0 + * + * @param string $userId + * @param ISearchRequest $searchRequest + * + * @return ISearchResult[] + */ + public function search(string $userId, ISearchRequest $searchRequest): array; + +} + diff --git a/lib/public/IAddressBook.php b/lib/public/IAddressBook.php index 67c34c9e8c9..4739e6f0c5b 100644 --- a/lib/public/IAddressBook.php +++ b/lib/public/IAddressBook.php @@ -55,16 +55,18 @@ namespace OCP { /** * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match - * @param array $options - for future use. One should always have options! + * @param array $options Options to define the output format + * - types boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array + * example: ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['type => 'HOME', 'value' => 'g@h.i']] * @return array an array of contacts which are arrays of key-value-pairs + * example result: + * [ + * ['id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'], + * ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['d@e.f', 'g@h.i']] + * ] * @since 5.0.0 */ public function search($pattern, $searchProperties, $options); - // // dummy results - // return array( - // array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'), - // array('id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => array('d@e.f', 'g@h.i')), - // ); /** * @param array $properties this array if key-value-pairs defines a contact diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php index 43543fdad47..7bcecbdc872 100644 --- a/lib/public/Share/IShare.php +++ b/lib/public/Share/IShare.php @@ -258,6 +258,23 @@ interface IShare { public function getExpirationDate(); /** + * set a label for a share, some shares, e.g. public links can have a label + * + * @param string $label + * @return \OCP\Share\IShare The modified object + * @since 15.0.0 + */ + public function setLabel($label); + + /** + * get label for the share, some shares, e.g. public links can have a label + * + * @return string + * @since 15.0.0 + */ + public function getLabel(); + + /** * Set the sharer of the path. * * @param string $sharedBy @@ -418,4 +435,25 @@ interface IShare { * @since 11.0.0 */ public function getNodeCacheEntry(); + + /** + * Sets a shares hide download state + * This is mainly for public shares. It will signal that the share page should + * hide download buttons etc. + * + * @param bool $ro + * @return IShare + * @since 15.0.0 + */ + public function setHideDownload(bool $hide): IShare; + + /** + * Gets a shares hide download state + * This is mainly for public shares. It will signal that the share page should + * hide download buttons etc. + * + * @return bool + * @since 15.0.0 + */ + public function getHideDownload(): bool; } diff --git a/resources/app-info-shipped.xsd b/resources/app-info-shipped.xsd index ae3aaee0996..f717ce0bc51 100644 --- a/resources/app-info-shipped.xsd +++ b/resources/app-info-shipped.xsd @@ -55,6 +55,8 @@ maxOccurs="1"/> <xs:element name="dashboard" type="dashboard" minOccurs="0" maxOccurs="1"/> + <xs:element name="fulltextsearch" type="fulltextsearch" + minOccurs="0" maxOccurs="1"/> <xs:element name="navigations" type="navigations" minOccurs="0" maxOccurs="1"/> <xs:element name="contactsmenu" type="contactsmenu" minOccurs="0" @@ -664,6 +666,15 @@ </xs:sequence> </xs:complexType> + <xs:complexType name="fulltextsearch"> + <xs:sequence> + <xs:element name="platform" type="php-class" minOccurs="0" + maxOccurs="unbounded"/> + <xs:element name="provider" type="php-class" minOccurs="0" + maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="php-class"> <xs:restriction base="xs:string"> <xs:pattern diff --git a/resources/app-info.xsd b/resources/app-info.xsd index fa06752c01d..e149339efec 100644 --- a/resources/app-info.xsd +++ b/resources/app-info.xsd @@ -53,6 +53,8 @@ maxOccurs="1"/> <xs:element name="dashboard" type="dashboard" minOccurs="0" maxOccurs="1"/> + <xs:element name="fulltextsearch" type="fulltextsearch" + minOccurs="0" maxOccurs="1"/> <xs:element name="navigations" type="navigations" minOccurs="0" maxOccurs="1"/> <xs:element name="contactsmenu" type="contactsmenu" minOccurs="0" @@ -63,6 +65,8 @@ maxOccurs="1" /> <xs:element name="trash" type="trash" minOccurs="0" maxOccurs="1" /> + <xs:element name="versions" type="versions" minOccurs="0" + maxOccurs="1" /> </xs:sequence> </xs:complexType> <xs:unique name="uniqueNameL10n"> @@ -655,6 +659,15 @@ </xs:sequence> </xs:complexType> + <xs:complexType name="fulltextsearch"> + <xs:sequence> + <xs:element name="platform" type="php-class" minOccurs="0" + maxOccurs="unbounded"/> + <xs:element name="provider" type="php-class" minOccurs="0" + maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="trash"> <xs:sequence> <xs:element name="backend" type="trash-backend" minOccurs="1" @@ -670,6 +683,21 @@ </xs:simpleContent> </xs:complexType> + <xs:complexType name="versions"> + <xs:sequence> + <xs:element name="backend" type="versions-backend" minOccurs="1" + maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="versions-backend"> + <xs:simpleContent> + <xs:extension base="php-class"> + <xs:attribute name="for" type="php-class" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:simpleType name="php-class"> <xs:restriction base="xs:string"> <xs:pattern diff --git a/settings/BackgroundJobs/VerifyUserData.php b/settings/BackgroundJobs/VerifyUserData.php index b4a60ec8405..56ebadff9c3 100644 --- a/settings/BackgroundJobs/VerifyUserData.php +++ b/settings/BackgroundJobs/VerifyUserData.php @@ -63,6 +63,9 @@ class VerifyUserData extends Job { /** @var string */ private $lookupServerUrl; + /** @var IConfig */ + private $config; + /** * VerifyUserData constructor. * @@ -85,6 +88,7 @@ class VerifyUserData extends Job { $lookupServerUrl = $config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com'); $this->lookupServerUrl = rtrim($lookupServerUrl, '/'); + $this->config = $config; } /** diff --git a/settings/Controller/CheckSetupController.php b/settings/Controller/CheckSetupController.php index 42bb4739870..fa4ed57ab95 100644 --- a/settings/Controller/CheckSetupController.php +++ b/settings/Controller/CheckSetupController.php @@ -287,12 +287,11 @@ class CheckSetupController extends Controller { */ private function forwardedForHeadersWorking() { $trustedProxies = $this->config->getSystemValue('trusted_proxies', []); - $remoteAddress = $this->request->getRemoteAddress(); + $remoteAddress = $this->request->getHeader('REMOTE_ADDR'); - if (is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) { - return false; + if (\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies)) { + return $remoteAddress !== $this->request->getRemoteAddress(); } - // either not enabled or working correctly return true; } diff --git a/settings/README.md b/settings/README.md deleted file mode 100644 index 71a77309bd0..00000000000 --- a/settings/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Settings section - -> Nextcloud settings with Vue - -## Build Setup - -``` bash -# install dependencies -make dev-setup - -# build for development -make build-js - -# build for development and watch edits -make watch-js - -# build for production with minification -make build-js-production - -# clean output files -make clean -``` diff --git a/settings/js/admin.js b/settings/js/admin.js index 35f3d949ab6..56bbaead520 100644 --- a/settings/js/admin.js +++ b/settings/js/admin.js @@ -66,11 +66,8 @@ $(document).ready(function(){ }); }); - $('#shareapiExpireAfterNDays').change(function() { - var value = $(this).val(); - if (value <= 0) { - $(this).val("1"); - } + $('#shareapiExpireAfterNDays').on('input', function() { + this.value = this.value.replace(/\D/g, ''); }); $('#shareAPI input:not(.noJSAutoUpdate)').change(function() { diff --git a/settings/l10n/eu.js b/settings/l10n/eu.js index e80f095eb15..94b51316809 100644 --- a/settings/l10n/eu.js +++ b/settings/l10n/eu.js @@ -120,6 +120,7 @@ OC.L10N.register( "User backend" : "Erabiltzaile jatorria", "Unlimited" : "Mugarik gabe", "Default quota" : "Kuota lehenetsia", + "App update" : "Aplikazioaren eguneraketa", "Error: This app can not be enabled because it makes the server unstable" : "Errorea: aplikazioa hau ezin da gaitu zerbitzaria ezegonkor izatea egiten duelako", "Your apps" : "Zure aplikazioak", "Disabled apps" : "Gaitu gabeko aplikazioak", @@ -334,6 +335,7 @@ OC.L10N.register( "You are using <strong>%s</strong> of <strong>%s</strong>" : "Zuk <strong>%s</strong> erabiltzen ari zara <strong>%s</strong>-tik", "You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)" : "<strong>%s</strong> erabiltzen ari zara,<strong>%s</strong>-koa (<strong>%s %%</strong>)", "You are member of the following groups:" : "Zuk honako talde kide zara:", + "iOS app" : "iOS aplikazioa", "Settings" : "Ezarpenak", "Show storage location" : "Erakutsi biltegiaren kokapena", "Show user backend" : "Bistaratu erabiltzaile motorra", @@ -344,6 +346,7 @@ OC.L10N.register( "Create" : "Sortu", "Admin Recovery Password" : "Administratzailearen pasahitza berreskuratzea", "Enter the recovery password in order to recover the users files during password change" : "Berreskuratze pasahitza idatzi pasahitz aldaketan erabiltzaileen fitxategiak berreskuratzeko", + "Group name" : "Taldearen izena", "Please enter storage quota (ex: \"512 MB\" or \"12 GB\")" : "Mesedez sartu biltegiratze kouta (adb: \"512 MB\" edo \"12 GB\")", "Other" : "Bestelakoa", "Quota" : "Kuota", diff --git a/settings/l10n/eu.json b/settings/l10n/eu.json index 6bf818481a2..58ceb052ea4 100644 --- a/settings/l10n/eu.json +++ b/settings/l10n/eu.json @@ -118,6 +118,7 @@ "User backend" : "Erabiltzaile jatorria", "Unlimited" : "Mugarik gabe", "Default quota" : "Kuota lehenetsia", + "App update" : "Aplikazioaren eguneraketa", "Error: This app can not be enabled because it makes the server unstable" : "Errorea: aplikazioa hau ezin da gaitu zerbitzaria ezegonkor izatea egiten duelako", "Your apps" : "Zure aplikazioak", "Disabled apps" : "Gaitu gabeko aplikazioak", @@ -332,6 +333,7 @@ "You are using <strong>%s</strong> of <strong>%s</strong>" : "Zuk <strong>%s</strong> erabiltzen ari zara <strong>%s</strong>-tik", "You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)" : "<strong>%s</strong> erabiltzen ari zara,<strong>%s</strong>-koa (<strong>%s %%</strong>)", "You are member of the following groups:" : "Zuk honako talde kide zara:", + "iOS app" : "iOS aplikazioa", "Settings" : "Ezarpenak", "Show storage location" : "Erakutsi biltegiaren kokapena", "Show user backend" : "Bistaratu erabiltzaile motorra", @@ -342,6 +344,7 @@ "Create" : "Sortu", "Admin Recovery Password" : "Administratzailearen pasahitza berreskuratzea", "Enter the recovery password in order to recover the users files during password change" : "Berreskuratze pasahitza idatzi pasahitz aldaketan erabiltzaileen fitxategiak berreskuratzeko", + "Group name" : "Taldearen izena", "Please enter storage quota (ex: \"512 MB\" or \"12 GB\")" : "Mesedez sartu biltegiratze kouta (adb: \"512 MB\" edo \"12 GB\")", "Other" : "Bestelakoa", "Quota" : "Kuota", diff --git a/settings/l10n/is.js b/settings/l10n/is.js index f88a5d79232..522917d8fbb 100644 --- a/settings/l10n/is.js +++ b/settings/l10n/is.js @@ -110,8 +110,10 @@ OC.L10N.register( "Groups" : "Hópar", "Group list is empty" : "Listi yfir hópa er tómur", "Unable to retrieve the group list" : "Tókst ekki að ná í lista yfir hópinn", + "Two-factor authentication can be enforced for all\tusers and specific groups. If they do not have a two-factor provider configured, they will be unable to log into the system." : "Hægt er að þvinga fram tveggja-þrepa auðkenningu fyrir alla notendur og/eða tiltekna hópa. Ef þeir eru ekki með tveggja-þrepa auðkenningarþjónustu uppsetta, munu þeir ekki geta skráð sig inn á kerfið.", "Enforce two-factor authentication" : "Þvinga fram tveggja-þrepa auðkenningu", "Limit to groups" : "Takmarka við hópa", + "Two-factor authentication is not enforced for\tmembers of the following groups." : "Tveggja-þrepa auðkenning er ekki þvinguð fram\tfyrir meðlimi eftirfarandi hópa.", "Official" : "Opinbert", "No results" : "Engar niðurstöður", "Visit website" : "Heimsækja vefsvæðið", diff --git a/settings/l10n/is.json b/settings/l10n/is.json index a069b428fae..7a79081a289 100644 --- a/settings/l10n/is.json +++ b/settings/l10n/is.json @@ -108,8 +108,10 @@ "Groups" : "Hópar", "Group list is empty" : "Listi yfir hópa er tómur", "Unable to retrieve the group list" : "Tókst ekki að ná í lista yfir hópinn", + "Two-factor authentication can be enforced for all\tusers and specific groups. If they do not have a two-factor provider configured, they will be unable to log into the system." : "Hægt er að þvinga fram tveggja-þrepa auðkenningu fyrir alla notendur og/eða tiltekna hópa. Ef þeir eru ekki með tveggja-þrepa auðkenningarþjónustu uppsetta, munu þeir ekki geta skráð sig inn á kerfið.", "Enforce two-factor authentication" : "Þvinga fram tveggja-þrepa auðkenningu", "Limit to groups" : "Takmarka við hópa", + "Two-factor authentication is not enforced for\tmembers of the following groups." : "Tveggja-þrepa auðkenning er ekki þvinguð fram\tfyrir meðlimi eftirfarandi hópa.", "Official" : "Opinbert", "No results" : "Engar niðurstöður", "Visit website" : "Heimsækja vefsvæðið", diff --git a/tests/Core/Controller/ClientFlowLoginControllerTest.php b/tests/Core/Controller/ClientFlowLoginControllerTest.php index 7fe87df026f..b54897ddc44 100644 --- a/tests/Core/Controller/ClientFlowLoginControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginControllerTest.php @@ -162,6 +162,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->expects($this->once()) ->method('getServerHost') ->willReturn('example.com'); + $this->request + ->method('getServerProtocol') + ->willReturn('https'); $expected = new TemplateResponse( 'core', @@ -172,7 +175,7 @@ class ClientFlowLoginControllerTest extends TestCase { 'instanceName' => 'ExampleCloud', 'urlGenerator' => $this->urlGenerator, 'stateToken' => 'StateToken', - 'serverHost' => 'example.com', + 'serverHost' => 'https://example.com', 'oauthState' => 'OauthStateToken', ], 'guest' @@ -218,6 +221,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->expects($this->once()) ->method('getServerHost') ->willReturn('example.com'); + $this->request + ->method('getServerProtocol') + ->willReturn('https'); $expected = new TemplateResponse( 'core', @@ -228,7 +234,7 @@ class ClientFlowLoginControllerTest extends TestCase { 'instanceName' => 'ExampleCloud', 'urlGenerator' => $this->urlGenerator, 'stateToken' => 'StateToken', - 'serverHost' => 'example.com', + 'serverHost' => 'https://example.com', 'oauthState' => 'OauthStateToken', ], 'guest' diff --git a/tests/Core/Controller/LoginControllerTest.php b/tests/Core/Controller/LoginControllerTest.php index f2e8d112b64..efe85d81e1c 100644 --- a/tests/Core/Controller/LoginControllerTest.php +++ b/tests/Core/Controller/LoginControllerTest.php @@ -199,6 +199,7 @@ class LoginControllerTest extends TestCase { 'alt_login' => [], 'resetPasswordLink' => null, 'throttle_delay' => 1000, + 'login_form_autocomplete' => 'off', ], 'guest' ); @@ -223,6 +224,7 @@ class LoginControllerTest extends TestCase { 'alt_login' => [], 'resetPasswordLink' => null, 'throttle_delay' => 1000, + 'login_form_autocomplete' => 'off', ], 'guest' ); @@ -255,10 +257,12 @@ class LoginControllerTest extends TestCase { ->method('isLoggedIn') ->willReturn(false); $this->config - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getSystemValue') - ->with('lost_password_link') - ->willReturn(false); + ->will($this->returnValueMap([ + ['login_form_autocomplete', true, true], + ['lost_password_link', '', false], + ])); $user = $this->createMock(IUser::class); $user ->expects($this->once()) @@ -281,6 +285,7 @@ class LoginControllerTest extends TestCase { 'alt_login' => [], 'resetPasswordLink' => false, 'throttle_delay' => 1000, + 'login_form_autocomplete' => 'on', ], 'guest' ); @@ -338,10 +343,12 @@ class LoginControllerTest extends TestCase { ->method('isLoggedIn') ->willReturn(false); $this->config - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getSystemValue') - ->with('lost_password_link') - ->willReturn(false); + ->will($this->returnValueMap([ + ['login_form_autocomplete', true, true], + ['lost_password_link', '', false], + ])); $user = $this->createMock(IUser::class); $user->expects($this->once()) ->method('canChangePassword') @@ -363,6 +370,7 @@ class LoginControllerTest extends TestCase { 'alt_login' => [], 'resetPasswordLink' => false, 'throttle_delay' => 1000, + 'login_form_autocomplete' => 'on', ], 'guest' ); diff --git a/tests/Settings/Controller/CheckSetupControllerTest.php b/tests/Settings/Controller/CheckSetupControllerTest.php index 6706573a1ad..34c7d19bd8d 100644 --- a/tests/Settings/Controller/CheckSetupControllerTest.php +++ b/tests/Settings/Controller/CheckSetupControllerTest.php @@ -295,38 +295,41 @@ class CheckSetupControllerTest extends TestCase { ); } - public function testForwardedForHeadersWorkingFalse() { + /** + * @dataProvider dataForwardedForHeadersWorking + * + * @param array $trustedProxies + * @param string $remoteAddrNoForwarded + * @param string $remoteAddr + * @param bool $result + */ + public function testForwardedForHeadersWorking(array $trustedProxies, string $remoteAddrNoForwarded, string $remoteAddr, bool $result) { $this->config->expects($this->once()) ->method('getSystemValue') ->with('trusted_proxies', []) - ->willReturn(['1.2.3.4']); + ->willReturn($trustedProxies); $this->request->expects($this->once()) + ->method('getHeader') + ->with('REMOTE_ADDR') + ->willReturn($remoteAddrNoForwarded); + $this->request->expects($this->any()) ->method('getRemoteAddress') - ->willReturn('1.2.3.4'); + ->willReturn($remoteAddr); - $this->assertFalse( - self::invokePrivate( - $this->checkSetupController, - 'forwardedForHeadersWorking' - ) + $this->assertEquals( + $result, + self::invokePrivate($this->checkSetupController, 'forwardedForHeadersWorking') ); } - public function testForwardedForHeadersWorkingTrue() { - $this->config->expects($this->once()) - ->method('getSystemValue') - ->with('trusted_proxies', []) - ->willReturn(['1.2.3.4']); - $this->request->expects($this->once()) - ->method('getRemoteAddress') - ->willReturn('4.3.2.1'); - - $this->assertTrue( - self::invokePrivate( - $this->checkSetupController, - 'forwardedForHeadersWorking' - ) - ); + public function dataForwardedForHeadersWorking() { + return [ + // description => trusted proxies, getHeader('REMOTE_ADDR'), getRemoteAddr, expected result + 'no trusted proxies' => [[], '2.2.2.2', '2.2.2.2', true], + 'trusted proxy, remote addr not trusted proxy' => [['1.1.1.1'], '2.2.2.2', '2.2.2.2', true], + 'trusted proxy, remote addr is trusted proxy, x-forwarded-for working' => [['1.1.1.1'], '1.1.1.1', '2.2.2.2', true], + 'trusted proxy, remote addr is trusted proxy, x-forwarded-for not set' => [['1.1.1.1'], '1.1.1.1', '1.1.1.1', false], + ]; } public function testCheck() { @@ -348,7 +351,8 @@ class CheckSetupControllerTest extends TestCase { ->will($this->returnValue(false)); $this->request->expects($this->once()) - ->method('getRemoteAddress') + ->method('getHeader') + ->with('REMOTE_ADDR') ->willReturn('4.3.2.1'); $client = $this->getMockBuilder('\OCP\Http\Client\IClient') diff --git a/tests/acceptance/features/app-files.feature b/tests/acceptance/features/app-files.feature index 74490180ad3..33bed4a3ef2 100644 --- a/tests/acceptance/features/app-files.feature +++ b/tests/acceptance/features/app-files.feature @@ -121,6 +121,32 @@ Feature: app-files And I open the Share menu Then I see that the Share menu is shown + Scenario: hide download in a public shared link + Given I act as John + And I am logged in + And I share the link for "welcome.txt" + And I set the download of the shared link as hidden + And I write down the shared link + When I act as Jane + And I visit the shared link I wrote down + And I see that the current page is the shared link I wrote down + Then I see that the download button is not shown + And I see that the Share menu button is not shown + + Scenario: show download again in a public shared link + Given I act as John + And I am logged in + And I share the link for "welcome.txt" + And I set the download of the shared link as hidden + And I set the download of the shared link as shown + And I write down the shared link + When I act as Jane + And I visit the shared link I wrote down + And I see that the current page is the shared link I wrote down + Then I see that the download button is shown + And I open the Share menu + And I see that the Share menu is shown + Scenario: creation is not possible by default in a public shared folder Given I act as John And I am logged in @@ -192,6 +218,10 @@ Feature: app-files When I protect the shared link with the password "abcdef" Then I see that the working icon for password protect is shown And I see that the working icon for password protect is eventually not shown + And I see that the link share is password protected + # As Talk is not enabled in the acceptance tests of the server the checkbox + # is never shown. + And I see that the checkbox to protect the password of the link share by Talk is not shown Scenario: access a shared link protected by password with a valid password Given I act as John diff --git a/tests/acceptance/features/bootstrap/FilesAppContext.php b/tests/acceptance/features/bootstrap/FilesAppContext.php index 408995b9a83..d9ac6431716 100644 --- a/tests/acceptance/features/bootstrap/FilesAppContext.php +++ b/tests/acceptance/features/bootstrap/FilesAppContext.php @@ -188,7 +188,7 @@ class FilesAppContext implements Context, ActorAwareInterface { * @return Locator */ public static function shareLinkRow() { - return Locator::forThe()->id("shareLink")-> + return Locator::forThe()->css(".linkShareView .shareWithList:first-child")-> descendantOf(self::detailsView())-> describedAs("Share link row in the details view in Files app"); } @@ -196,13 +196,21 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @return Locator */ - public static function shareLinkCheckbox() { - // forThe()->checkbox("Enable") can not be used here; that would return - // the checkbox itself, but the element that the user interacts with is - // the label. - return Locator::forThe()->xpath("//label[normalize-space() = 'Enable']")-> + public static function shareLinkAddNewButton() { + // When there is no link share the "Add new share" item is shown instead + // of the menu button as a direct child of ".share-menu". + return Locator::forThe()->css(".share-menu > .new-share")-> descendantOf(self::shareLinkRow())-> - describedAs("Share link checkbox in the details view in Files app"); + describedAs("Add new share link button in the details view in Files app"); + } + + /** + * @return Locator + */ + public static function copyLinkButton() { + return Locator::forThe()->css("a.clipboard-button")-> + descendantOf(self::shareLinkRow())-> + describedAs("Copy link button in the details view in Files app"); } /** @@ -226,10 +234,22 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @return Locator */ - public static function copyUrlMenuItem() { - return Locator::forThe()->xpath("//a[normalize-space() = 'Copy link']")-> + public static function hideDownloadCheckbox() { + // forThe()->checkbox("Hide download") can not be used here; that would + // return the checkbox itself, but the element that the user interacts + // with is the label. + return Locator::forThe()->xpath("//label[normalize-space() = 'Hide download']")-> + descendantOf(self::shareLinkMenu())-> + describedAs("Hide download checkbox in the details view in Files app"); + } + + /** + * @return Locator + */ + public static function hideDownloadCheckboxInput() { + return Locator::forThe()->checkbox("Hide download")-> descendantOf(self::shareLinkMenu())-> - describedAs("Copy link menu item in the share link menu in the details view in Files app"); + describedAs("Hide download checkbox input in the details view in Files app"); } /** @@ -259,6 +279,15 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @return Locator */ + public static function passwordProtectCheckboxInput() { + return Locator::forThe()->checkbox("Password protect")-> + descendantOf(self::shareLinkMenu())-> + describedAs("Password protect checkbox input in the details view in Files app"); + } + + /** + * @return Locator + */ public static function passwordProtectField() { return Locator::forThe()->css(".linkPassText")->descendantOf(self::shareLinkMenu())-> describedAs("Password protect field in the details view in Files app"); @@ -273,6 +302,27 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @return Locator + */ + public static function passwordProtectByTalkCheckbox() { + // forThe()->checkbox("Password protect by Talk") can not be used here; + // that would return the checkbox itself, but the element that the user + // interacts with is the label. + return Locator::forThe()->xpath("//label[normalize-space() = 'Password protect by Talk']")-> + descendantOf(self::shareLinkMenu())-> + describedAs("Password protect by Talk checkbox in the details view in Files app"); + } + + /** + * @return Locator + */ + public static function passwordProtectByTalkCheckboxInput() { + return Locator::forThe()->checkbox("Password protect by Talk")-> + descendantOf(self::shareLinkMenu())-> + describedAs("Password protect by Talk checkbox input in the details view in Files app"); + } + + /** * @Given I close the details view */ public function iCloseTheDetailsView() { @@ -299,21 +349,27 @@ class FilesAppContext implements Context, ActorAwareInterface { public function iShareTheLinkFor($fileName) { $this->actor->find(FileListContext::shareActionForFile(self::currentSectionMainView(), $fileName), 10)->click(); - $this->actor->find(self::shareLinkCheckbox(), 5)->click(); + $this->actor->find(self::shareLinkAddNewButton(), 5)->click(); + + // Wait until the menu was opened after the share creation to continue. + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, + self::shareLinkMenu(), + $timeout = 5 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The share link menu is not open yet after $timeout seconds"); + } } /** * @Given I write down the shared link */ public function iWriteDownTheSharedLink() { - $this->showShareLinkMenuIfNeeded(); - - $this->actor->find(self::copyUrlMenuItem(), 2)->click(); + $this->actor->find(self::copyLinkButton(), 10)->click(); // Clicking on the menu item copies the link to the clipboard, but it is // not possible to access that value from the acceptance tests. Due to // this the value of the attribute that holds the URL is used instead. - $this->actor->getSharedNotebook()["shared link"] = $this->actor->find(self::copyUrlMenuItem(), 2)->getWrappedElement()->getAttribute("data-clipboard-text"); + $this->actor->getSharedNotebook()["shared link"] = $this->actor->find(self::copyLinkButton(), 2)->getWrappedElement()->getAttribute("data-clipboard-text"); } /** @@ -335,6 +391,28 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @When I set the download of the shared link as hidden + */ + public function iSetTheDownloadOfTheSharedLinkAsHidden() { + $this->showShareLinkMenuIfNeeded(); + + $this->iSeeThatTheDownloadOfTheLinkShareIsShown(); + + $this->actor->find(self::hideDownloadCheckbox(), 2)->click(); + } + + /** + * @When I set the download of the shared link as shown + */ + public function iSetTheDownloadOfTheSharedLinkAsShown() { + $this->showShareLinkMenuIfNeeded(); + + $this->iSeeThatTheDownloadOfTheLinkShareIsHidden(); + + $this->actor->find(self::hideDownloadCheckbox(), 2)->click(); + } + + /** * @When I set the shared link as editable */ public function iSetTheSharedLinkAsEditable() { @@ -355,6 +433,28 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @When I set the password of the shared link as protected by Talk + */ + public function iSetThePasswordOfTheSharedLinkAsProtectedByTalk() { + $this->showShareLinkMenuIfNeeded(); + + $this->iSeeThatThePasswordOfTheLinkShareIsNotProtectedByTalk(); + + $this->actor->find(self::passwordProtectByTalkCheckbox(), 2)->click(); + } + + /** + * @When I set the password of the shared link as not protected by Talk + */ + public function iSetThePasswordOfTheSharedLinkAsNotProtectedByTalk() { + $this->showShareLinkMenuIfNeeded(); + + $this->iSeeThatThePasswordOfTheLinkShareIsProtectedByTalk(); + + $this->actor->find(self::passwordProtectByTalkCheckbox(), 2)->click(); + } + + /** * @Then I see that the current page is the Files app */ public function iSeeThatTheCurrentPageIsTheFilesApp() { @@ -461,6 +561,24 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @Then I see that the download of the link share is hidden + */ + public function iSeeThatTheDownloadOfTheLinkShareIsHidden() { + $this->showShareLinkMenuIfNeeded(); + + PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::hideDownloadCheckboxInput(), 10)->isChecked()); + } + + /** + * @Then I see that the download of the link share is shown + */ + public function iSeeThatTheDownloadOfTheLinkShareIsShown() { + $this->showShareLinkMenuIfNeeded(); + + PHPUnit_Framework_Assert::assertFalse($this->actor->find(self::hideDownloadCheckboxInput(), 10)->isChecked()); + } + + /** * @Then I see that the working icon for password protect is shown */ public function iSeeThatTheWorkingIconForPasswordProtectIsShown() { @@ -480,6 +598,47 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @Then I see that the link share is password protected + */ + public function iSeeThatTheLinkShareIsPasswordProtected() { + $this->showShareLinkMenuIfNeeded(); + + PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::passwordProtectCheckboxInput(), 10)->isChecked(), "Password protect checkbox is checked"); + PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::passwordProtectField(), 10)->isVisible(), "Password protect field is visible"); + } + + /** + * @Then I see that the password of the link share is protected by Talk + */ + public function iSeeThatThePasswordOfTheLinkShareIsProtectedByTalk() { + $this->showShareLinkMenuIfNeeded(); + + PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::passwordProtectByTalkCheckboxInput(), 10)->isChecked()); + } + + /** + * @Then I see that the password of the link share is not protected by Talk + */ + public function iSeeThatThePasswordOfTheLinkShareIsNotProtectedByTalk() { + $this->showShareLinkMenuIfNeeded(); + + PHPUnit_Framework_Assert::assertFalse($this->actor->find(self::passwordProtectByTalkCheckboxInput(), 10)->isChecked()); + } + + /** + * @Then I see that the checkbox to protect the password of the link share by Talk is not shown + */ + public function iSeeThatTheCheckboxToProtectThePasswordOfTheLinkShareByTalkIsNotShown() { + $this->showShareLinkMenuIfNeeded(); + + try { + PHPUnit_Framework_Assert::assertFalse( + $this->actor->find(self::passwordProtectByTalkCheckbox())->isVisible()); + } catch (NoSuchElementException $exception) { + } + } + + /** * @Given I share the link for :fileName protected by the password :password */ public function iShareTheLinkForProtectedByThePassword($fileName, $password) { diff --git a/tests/acceptance/features/bootstrap/FilesSharingAppContext.php b/tests/acceptance/features/bootstrap/FilesSharingAppContext.php index 1fe12d5f42d..531184442dd 100644 --- a/tests/acceptance/features/bootstrap/FilesSharingAppContext.php +++ b/tests/acceptance/features/bootstrap/FilesSharingAppContext.php @@ -104,6 +104,14 @@ class FilesSharingAppContext implements Context, ActorAwareInterface { } /** + * @return Locator + */ + public static function downloadButton() { + return Locator::forThe()->id("downloadFile")-> + describedAs("Download button in Shared file page"); + } + + /** * @When I visit the shared link I wrote down */ public function iVisitTheSharedLinkIWroteDown() { @@ -199,10 +207,42 @@ class FilesSharingAppContext implements Context, ActorAwareInterface { } /** + * @Then I see that the Share menu button is not shown + */ + public function iSeeThatTheShareMenuButtonIsNotShown() { + try { + PHPUnit_Framework_Assert::assertFalse( + $this->actor->find(self::shareMenuButton())->isVisible()); + } catch (NoSuchElementException $exception) { + } + } + + /** * @Then I see that the shared file preview shows the text :text */ public function iSeeThatTheSharedFilePreviewShowsTheText($text) { PHPUnit_Framework_Assert::assertContains($text, $this->actor->find(self::textPreview(), 10)->getText()); } + /** + * @Then I see that the download button is shown + */ + public function iSeeThatTheDownloadButtonIsShown() { + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, self::downloadButton(), $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The download button is not visible yet after $timeout seconds"); + } + } + + /** + * @Then I see that the download button is not shown + */ + public function iSeeThatTheDownloadButtonIsNotShown() { + try { + PHPUnit_Framework_Assert::assertFalse( + $this->actor->find(self::downloadButton())->isVisible()); + } catch (NoSuchElementException $exception) { + } + } + } diff --git a/tests/lib/AppFramework/Http/RequestTest.php b/tests/lib/AppFramework/Http/RequestTest.php index a715eaa9599..c0e8dc97ef2 100644 --- a/tests/lib/AppFramework/Http/RequestTest.php +++ b/tests/lib/AppFramework/Http/RequestTest.php @@ -486,6 +486,35 @@ class RequestTest extends \Test\TestCase { $this->assertSame('10.4.0.5', $request->getRemoteAddress()); } + public function testGetRemoteAddressIPv6WithSingleTrustedRemote() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['2001:db8:85a3:8d3:1319:8a2e:370:7348'])); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('forwarded_for_headers') + ->will($this->returnValue(['HTTP_X_FORWARDED'])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '2001:db8:85a3:8d3:1319:8a2e:370:7348', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('10.4.0.5', $request->getRemoteAddress()); + } + public function testGetRemoteAddressVerifyPriorityHeader() { $this->config ->expects($this->at(0)) @@ -519,6 +548,92 @@ class RequestTest extends \Test\TestCase { $this->assertSame('192.168.0.233', $request->getRemoteAddress()); } + public function testGetRemoteAddressIPv6VerifyPriorityHeader() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['2001:db8:85a3:8d3:1319:8a2e:370:7348'])); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('forwarded_for_headers') + ->will($this->returnValue([ + 'HTTP_CLIENT_IP', + 'HTTP_X_FORWARDED_FOR', + 'HTTP_X_FORWARDED' + ])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '2001:db8:85a3:8d3:1319:8a2e:370:7348', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('192.168.0.233', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressWithMatchingCidrTrustedRemote() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['192.168.2.0/24'])); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('forwarded_for_headers') + ->will($this->returnValue(['HTTP_X_FORWARDED_FOR'])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '192.168.2.99', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('192.168.0.233', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressWithNotMatchingCidrTrustedRemote() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['192.168.2.0/24'])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '192.168.3.99', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('192.168.3.99', $request->getRemoteAddress()); + } + /** * @return array */ diff --git a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php index 8b005bd8bdb..57144d0f00d 100644 --- a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php +++ b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php @@ -22,18 +22,17 @@ namespace Test\Authentication\Token; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Token\DefaultToken; use OC\Authentication\Token\DefaultTokenMapper; use OC\Authentication\Token\DefaultTokenProvider; -use OC\Authentication\Token\ExpiredTokenException; use OC\Authentication\Token\IToken; use OC\Authentication\Token\PublicKeyToken; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\ILogger; -use OCP\IUser; use OCP\Security\ICrypto; use Test\TestCase; diff --git a/tests/lib/Authentication/Token/PublicKeyTokenProviderTest.php b/tests/lib/Authentication/Token/PublicKeyTokenProviderTest.php index 02ec62d3d77..ce64878bf5e 100644 --- a/tests/lib/Authentication/Token/PublicKeyTokenProviderTest.php +++ b/tests/lib/Authentication/Token/PublicKeyTokenProviderTest.php @@ -23,19 +23,17 @@ namespace Test\Authentication\Token; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; -use OC\Authentication\Exceptions\PasswordlessTokenException; use OC\Authentication\Token\DefaultToken; use OC\Authentication\Token\PublicKeyToken; use OC\Authentication\Token\PublicKeyTokenMapper; use OC\Authentication\Token\PublicKeyTokenProvider; -use OC\Authentication\Token\ExpiredTokenException; use OC\Authentication\Token\IToken; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\ILogger; -use OCP\IUser; use OCP\Security\ICrypto; use Test\TestCase; diff --git a/tests/lib/Collaboration/Collaborators/MailPluginTest.php b/tests/lib/Collaboration/Collaborators/MailPluginTest.php index 775941bd440..a9d0244d38c 100644 --- a/tests/lib/Collaboration/Collaborators/MailPluginTest.php +++ b/tests/lib/Collaboration/Collaborators/MailPluginTest.php @@ -120,16 +120,20 @@ class MailPluginTest extends TestCase { public function dataGetEmail() { return [ + // data set 0 ['test', [], true, ['emails' => [], 'exact' => ['emails' => []]], false, false], + // data set 1 ['test', [], false, ['emails' => [], 'exact' => ['emails' => []]], false, false], + // data set 2 [ 'test@remote.com', [], true, - ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], + ['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@remote.com', 'label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], false, false, ], + // data set 3 [ // no valid email address 'test@remote', [], @@ -138,26 +142,31 @@ class MailPluginTest extends TestCase { false, false, ], + // data set 4 [ 'test@remote.com', [], false, - ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], + ['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@remote.com', 'label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], false, false, ], + // data set 5 [ 'test', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -165,22 +174,26 @@ class MailPluginTest extends TestCase { ], ], true, - ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => []]], + ['emails' => [['uuid' => 'uid1', 'name' => 'User @ Localhost', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => []]], false, false, ], + // data set 6 [ 'test', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -192,18 +205,22 @@ class MailPluginTest extends TestCase { false, false, ], + // data set 7 [ 'test@remote.com', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -211,22 +228,26 @@ class MailPluginTest extends TestCase { ], ], true, - ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], + ['emails' => [['uuid' => 'uid1', 'name' => 'User @ Localhost', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => [['label' => 'test@remote.com', 'uuid' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], false, false, ], + // data set 8 [ 'test@remote.com', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -234,22 +255,26 @@ class MailPluginTest extends TestCase { ], ], false, - ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], + ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'uuid' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]], false, false, ], + // data set 9 [ 'username@localhost', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -257,22 +282,26 @@ class MailPluginTest extends TestCase { ], ], true, - ['emails' => [], 'exact' => ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]], + ['emails' => [], 'exact' => ['emails' => [['name' => 'User @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]], true, false, ], + // data set 10 [ 'username@localhost', [ [ + 'UID' => 'uid1', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -280,23 +309,27 @@ class MailPluginTest extends TestCase { ], ], false, - ['emails' => [], 'exact' => ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]], + ['emails' => [], 'exact' => ['emails' => [['name' => 'User @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]], true, false, ], + // data set 11 // contact with space [ 'user name@localhost', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User Name @ Localhost', 'EMAIL' => [ 'user name@localhost', @@ -304,23 +337,27 @@ class MailPluginTest extends TestCase { ], ], false, - ['emails' => [], 'exact' => ['emails' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'user name@localhost']]]]], + ['emails' => [], 'exact' => ['emails' => [['name' => 'User Name @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'user name@localhost']]]]], true, false, ], + // data set 12 // remote with space, no contact [ 'user space@remote.com', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'EMAIL' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'EMAIL' => [ 'username@localhost', @@ -332,11 +369,13 @@ class MailPluginTest extends TestCase { false, false, ], + // data set 13 // Local user found by email [ 'test@example.com', [ [ + 'UID' => 'uid1', 'FN' => 'User', 'EMAIL' => ['test@example.com'], 'CLOUD' => ['test@localhost'], @@ -344,15 +383,17 @@ class MailPluginTest extends TestCase { ] ], false, - ['users' => [], 'exact' => ['users' => [['label' => 'User (test@example.com)','value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test'],]]]], + ['users' => [], 'exact' => ['users' => [['uuid' => 'uid1', 'name' => 'User', 'label' => 'User (test@example.com)','value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test'],]]]], true, false, ], + // data set 14 // Current local user found by email => no result [ 'test@example.com', [ [ + 'UID' => 'uid1', 'FN' => 'User', 'EMAIL' => ['test@example.com'], 'CLOUD' => ['current@localhost'], @@ -364,29 +405,34 @@ class MailPluginTest extends TestCase { false, false, ], + // data set 15 // Pagination and "more results" for user matches byyyyyyy emails [ 'test@example', [ [ + 'UID' => 'uid1', 'FN' => 'User1', 'EMAIL' => ['test@example.com'], 'CLOUD' => ['test1@localhost'], 'isLocalSystemBook' => true, ], [ + 'UID' => 'uid2', 'FN' => 'User2', 'EMAIL' => ['test@example.de'], 'CLOUD' => ['test2@localhost'], 'isLocalSystemBook' => true, ], [ + 'UID' => 'uid3', 'FN' => 'User3', 'EMAIL' => ['test@example.org'], 'CLOUD' => ['test3@localhost'], 'isLocalSystemBook' => true, ], [ + 'UID' => 'uid4', 'FN' => 'User4', 'EMAIL' => ['test@example.net'], 'CLOUD' => ['test4@localhost'], @@ -395,32 +441,37 @@ class MailPluginTest extends TestCase { ], true, ['users' => [ - ['label' => 'User1 (test@example.com)', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], - ['label' => 'User2 (test@example.de)', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']], + ['uuid' => 'uid1', 'name' => 'User1', 'label' => 'User1 (test@example.com)', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], + ['uuid' => 'uid2', 'name' => 'User2', 'label' => 'User2 (test@example.de)', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']], ], 'emails' => [], 'exact' => ['users' => [], 'emails' => []]], false, true, ], + // data set 16 // Pagination and "more results" for normal emails [ 'test@example', [ [ + 'UID' => 'uid1', 'FN' => 'User1', 'EMAIL' => ['test@example.com'], 'CLOUD' => ['test1@localhost'], ], [ + 'UID' => 'uid2', 'FN' => 'User2', 'EMAIL' => ['test@example.de'], 'CLOUD' => ['test2@localhost'], ], [ + 'UID' => 'uid3', 'FN' => 'User3', 'EMAIL' => ['test@example.org'], 'CLOUD' => ['test3@localhost'], ], [ + 'UID' => 'uid4', 'FN' => 'User4', 'EMAIL' => ['test@example.net'], 'CLOUD' => ['test4@localhost'], @@ -428,12 +479,45 @@ class MailPluginTest extends TestCase { ], true, ['emails' => [ - ['label' => 'User1 (test@example.com)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@example.com']], - ['label' => 'User2 (test@example.de)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@example.de']], + ['uuid' => 'uid1', 'name' => 'User1', 'type' => '', 'label' => 'User1 (test@example.com)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@example.com']], + ['uuid' => 'uid2', 'name' => 'User2', 'type' => '', 'label' => 'User2 (test@example.de)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@example.de']], ], 'exact' => ['emails' => []]], false, true, ], + // data set 17 + // multiple email addresses with type + [ + 'User Name', + [ + [ + 'UID' => 'uid3', + 'FN' => 'User3', + ], + [ + 'UID' => 'uid2', + 'FN' => 'User2', + 'EMAIL' => [ + ], + ], + [ + 'UID' => 'uid1', + 'FN' => 'User Name', + 'EMAIL' => [ + ['type' => 'HOME', 'value' => 'username@localhost'], + ['type' => 'WORK', 'value' => 'username@other'], + ], + ], + ], + false, + ['emails' => [ + ], 'exact' => ['emails' => [ + ['name' => 'User Name', 'uuid' => 'uid1', 'type' => 'HOME', 'label' => 'User Name (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']], + ['name' => 'User Name', 'uuid' => 'uid1', 'type' => 'WORK', 'label' => 'User Name (username@other)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@other']] + ]]], + false, + false, + ], ]; } @@ -513,7 +597,7 @@ class MailPluginTest extends TestCase { 'UID' => 'User' ] ], - ['users' => [['label' => 'User (test@example.com)','value' => ['shareType' => 0, 'shareWith' => 'test'],]], 'emails' => [], 'exact' => ['emails' => [], 'users' => []]], + ['users' => [['label' => 'User (test@example.com)', 'uuid' => 'User', 'name' => 'User', 'value' => ['shareType' => 0, 'shareWith' => 'test'],]], 'emails' => [], 'exact' => ['emails' => [], 'users' => []]], false, false, [ @@ -553,7 +637,7 @@ class MailPluginTest extends TestCase { 'UID' => 'User' ] ], - ['emails' => [], 'exact' => ['emails' => [['label' => 'test@example.com', 'value' => ['shareType' => 4,'shareWith' => 'test@example.com']]]]], + ['emails' => [], 'exact' => ['emails' => [['label' => 'test@example.com', 'uuid' => 'test@example.com', 'value' => ['shareType' => 4,'shareWith' => 'test@example.com']]]]], false, false, [ diff --git a/tests/lib/Collaboration/Collaborators/RemotePluginTest.php b/tests/lib/Collaboration/Collaborators/RemotePluginTest.php index aa009a7134b..aff68185767 100644 --- a/tests/lib/Collaboration/Collaborators/RemotePluginTest.php +++ b/tests/lib/Collaboration/Collaborators/RemotePluginTest.php @@ -31,10 +31,17 @@ use OCP\Collaboration\Collaborators\SearchResultType; use OCP\Contacts\IManager; use OCP\Federation\ICloudIdManager; use OCP\IConfig; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IUserSession; use OCP\Share; use Test\TestCase; class RemotePluginTest extends TestCase { + + /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $userManager; + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ protected $config; @@ -53,6 +60,7 @@ class RemotePluginTest extends TestCase { public function setUp() { parent::setUp(); + $this->userManager = $this->createMock(IUserManager::class); $this->config = $this->createMock(IConfig::class); $this->contactsManager = $this->createMock(IManager::class); $this->cloudIdManager = new CloudIdManager(); @@ -60,7 +68,15 @@ class RemotePluginTest extends TestCase { } public function instantiatePlugin() { - $this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config); + $user = $this->createMock(IUser::class); + $user->expects($this->any()) + ->method('getUID') + ->willReturn('admin'); + $userSession = $this->createMock(IUserSession::class); + $userSession->expects($this->any()) + ->method('getUser') + ->willReturn($user); + $this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config, $this->userManager, $userSession); } /** @@ -152,14 +168,17 @@ class RemotePluginTest extends TestCase { 'test', [ [ + 'UID' => 'uid', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', @@ -167,7 +186,7 @@ class RemotePluginTest extends TestCase { ], ], true, - ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => []]], + ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => []]], false, true, ], @@ -175,14 +194,17 @@ class RemotePluginTest extends TestCase { 'test', [ [ + 'UID' => 'uid', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', @@ -198,14 +220,17 @@ class RemotePluginTest extends TestCase { 'test@remote', [ [ + 'UID' => 'uid', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', @@ -213,7 +238,7 @@ class RemotePluginTest extends TestCase { ], ], true, - ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]]]], + ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid', 'type' => '', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]]]], false, true, ], @@ -221,14 +246,17 @@ class RemotePluginTest extends TestCase { 'test@remote', [ [ + 'UID' => 'uid', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', @@ -244,14 +272,17 @@ class RemotePluginTest extends TestCase { 'username@localhost', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => '2', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', @@ -259,7 +290,7 @@ class RemotePluginTest extends TestCase { ], ], true, - ['remotes' => [], 'exact' => ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]], + ['remotes' => [], 'exact' => ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]], true, true, ], @@ -267,14 +298,17 @@ class RemotePluginTest extends TestCase { 'username@localhost', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', @@ -282,7 +316,7 @@ class RemotePluginTest extends TestCase { ], ], false, - ['remotes' => [], 'exact' => ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]], + ['remotes' => [], 'exact' => ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]], true, true, ], @@ -291,14 +325,17 @@ class RemotePluginTest extends TestCase { 'user name@localhost', [ [ + 'UID' => 'uid1', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid3', 'FN' => 'User Name @ Localhost', 'CLOUD' => [ 'user name@localhost', @@ -306,7 +343,7 @@ class RemotePluginTest extends TestCase { ], ], false, - ['remotes' => [], 'exact' => ['remotes' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']]]]], + ['remotes' => [], 'exact' => ['remotes' => [['name' => 'User Name @ Localhost', 'label' => 'User Name @ Localhost (user name@localhost)', 'uuid' => 'uid3', 'type' => '', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']]]]], true, true, ], @@ -315,14 +352,17 @@ class RemotePluginTest extends TestCase { 'user space@remote', [ [ + 'UID' => 'uid3', 'FN' => 'User3 @ Localhost', ], [ + 'UID' => 'uid2', 'FN' => 'User2 @ Localhost', 'CLOUD' => [ ], ], [ + 'UID' => 'uid1', 'FN' => 'User @ Localhost', 'CLOUD' => [ 'username@localhost', diff --git a/tests/lib/Files/Storage/Storage.php b/tests/lib/Files/Storage/Storage.php index 04aafece2e3..a25a3f74f9e 100644 --- a/tests/lib/Files/Storage/Storage.php +++ b/tests/lib/Files/Storage/Storage.php @@ -23,6 +23,7 @@ namespace Test\Files\Storage; use OC\Files\Cache\Watcher; +use OCP\Files\Storage\IWriteStreamStorage; abstract class Storage extends \Test\TestCase { /** @@ -628,4 +629,20 @@ abstract class Storage extends \Test\TestCase { $this->instance->rename('bar.txt.part', 'bar.txt'); $this->assertEquals('bar', $this->instance->file_get_contents('bar.txt')); } + + public function testWriteStream() { + $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; + + if (!$this->instance->instanceOfStorage(IWriteStreamStorage::class)) { + $this->markTestSkipped('Not a WriteSteamStorage'); + } + /** @var IWriteStreamStorage $storage */ + $storage = $this->instance; + + $source = fopen($textFile, 'r'); + + $storage->writeStream('test.txt', $source); + $this->assertTrue($storage->file_exists('test.txt')); + $this->assertEquals(file_get_contents($textFile), $storage->file_get_contents('test.txt')); + } } diff --git a/tests/lib/Files/Stream/CountReadStreamTest.php b/tests/lib/Files/Stream/CountReadStreamTest.php new file mode 100644 index 00000000000..99291d1644f --- /dev/null +++ b/tests/lib/Files/Stream/CountReadStreamTest.php @@ -0,0 +1,49 @@ +<?php declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace Test\Files\Stream; + +use OC\Files\Stream\CountReadStream; +use Test\TestCase; + +class CountReadStreamTest extends TestCase { + private function getStream($data) { + $handle = fopen('php://temp', 'w+'); + fwrite($handle, $data); + rewind($handle); + return $handle; + } + + public function testBasicCount() { + $source = $this->getStream('foo'); + $stream = CountReadStream::wrap($source, function ($size) { + $this->assertEquals(3, $size); + }); + stream_get_contents($stream); + } + + public function testLarger() { + $stream = CountReadStream::wrap(fopen(__DIR__ . '/../../../data/testimage.mp4', 'r'), function ($size) { + $this->assertEquals(383631, $size); + }); + stream_get_contents($stream); + } +} diff --git a/tests/lib/Mail/MailerTest.php b/tests/lib/Mail/MailerTest.php index d724cd630d3..ddae38ff54d 100644 --- a/tests/lib/Mail/MailerTest.php +++ b/tests/lib/Mail/MailerTest.php @@ -55,7 +55,13 @@ class MailerTest extends TestCase { ->with('mail_smtpmode', 'smtp') ->will($this->returnValue('sendmail')); - $this->assertEquals(new \Swift_SendmailTransport('/usr/sbin/sendmail -bs'), self::invokePrivate($this->mailer, 'getSendMailInstance')); + $path = \OC_Helper::findBinaryPath('sendmail'); + if ($path === null) { + $path = '/usr/sbin/sendmail'; + } + + $expected = new \Swift_SendmailTransport($path . ' -bs'); + $this->assertEquals($expected, self::invokePrivate($this->mailer, 'getSendMailInstance')); } public function testGetSendMailInstanceSendMailQmail() { diff --git a/tests/lib/Preview/GeneratorTest.php b/tests/lib/Preview/GeneratorTest.php index 64786fa9fe8..565b526b659 100644 --- a/tests/lib/Preview/GeneratorTest.php +++ b/tests/lib/Preview/GeneratorTest.php @@ -104,7 +104,7 @@ class GeneratorTest extends \Test\TestCase { $previewFile = $this->createMock(ISimpleFile::class); $previewFolder->method('getFile') - ->with($this->equalTo('128-128.png')) + ->with($this->equalTo('256-256.png')) ->willReturn($previewFile); $this->eventDispatcher->expects($this->once()) @@ -212,7 +212,7 @@ class GeneratorTest extends \Test\TestCase { ->will($this->returnCallback(function($filename) use ($maxPreview, $previewFile) { if ($filename === '2048-2048-max.png') { return $maxPreview; - } else if ($filename === '128-128.png') { + } else if ($filename === '256-256.png') { return $previewFile; } $this->fail('Unexpected file'); @@ -223,7 +223,7 @@ class GeneratorTest extends \Test\TestCase { ->with($this->equalTo('my data')); $previewFolder->method('getFile') - ->with($this->equalTo('128-128.png')) + ->with($this->equalTo('256-256.png')) ->willThrowException(new NotFoundException()); $image = $this->createMock(IImage::class); @@ -233,7 +233,7 @@ class GeneratorTest extends \Test\TestCase { $image->expects($this->once()) ->method('resize') - ->with(128); + ->with(256); $image->method('data') ->willReturn('my resized data'); $image->method('valid')->willReturn(true); @@ -328,8 +328,8 @@ class GeneratorTest extends \Test\TestCase { return [ [1024, 2048, 512, 512, false, IPreview::MODE_FILL, 256, 512], [1024, 2048, 512, 512, false, IPreview::MODE_COVER, 512, 1024], - [1024, 2048, 512, 512, true, IPreview::MODE_FILL, 512, 512], - [1024, 2048, 512, 512, true, IPreview::MODE_COVER, 512, 512], + [1024, 2048, 512, 512, true, IPreview::MODE_FILL, 1024, 1024], + [1024, 2048, 512, 512, true, IPreview::MODE_COVER, 1024, 1024], [1024, 2048, -1, 512, false, IPreview::MODE_COVER, 256, 512], [1024, 2048, 512, -1, false, IPreview::MODE_FILL, 512, 1024], @@ -343,14 +343,20 @@ class GeneratorTest extends \Test\TestCase { [2048, 1024, 512, 512, false, IPreview::MODE_FILL, 512, 256], [2048, 1024, 512, 512, false, IPreview::MODE_COVER, 1024, 512], - [2048, 1024, 512, 512, true, IPreview::MODE_FILL, 512, 512], - [2048, 1024, 512, 512, true, IPreview::MODE_COVER, 512, 512], + [2048, 1024, 512, 512, true, IPreview::MODE_FILL, 1024, 1024], + [2048, 1024, 512, 512, true, IPreview::MODE_COVER, 1024, 1024], [2048, 1024, -1, 512, false, IPreview::MODE_FILL, 1024, 512], [2048, 1024, 512, -1, false, IPreview::MODE_COVER, 512, 256], [2048, 1024, 4096, 1024, true, IPreview::MODE_FILL, 2048, 512], [2048, 1024, 4096, 1024, true, IPreview::MODE_COVER, 2048, 512], + + //Test minimum size + [2048, 1024, 32, 32, false, IPreview::MODE_FILL, 64, 32], + [2048, 1024, 32, 32, false, IPreview::MODE_COVER, 64, 32], + [2048, 1024, 32, 32, true, IPreview::MODE_FILL, 64, 64], + [2048, 1024, 32, 32, true, IPreview::MODE_COVER, 64, 64], ]; } diff --git a/tests/lib/Repair/SetVcardDatabaseUIDTest.php b/tests/lib/Repair/SetVcardDatabaseUIDTest.php new file mode 100644 index 00000000000..97da3c6a901 --- /dev/null +++ b/tests/lib/Repair/SetVcardDatabaseUIDTest.php @@ -0,0 +1,121 @@ +<?php +/** + * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace Test\Repair; + +use OCP\IConfig; +use OC\Repair\NC15\SetVcardDatabaseUID; +use Test\TestCase; + +/** + * @group DB + */ +class SetVcardDatabaseUIDTest extends TestCase { + + /** @var SetVcardDatabaseUID */ + private $repair; + + /** @var IConfig */ + private $config; + + protected function setUp() { + parent::setUp(); + + $this->config = $this->createMock(IConfig::class); + $this->repair = new SetVcardDatabaseUID(\OC::$server->getDatabaseConnection(), $this->config); + } + + protected function tearDown() { + return parent::tearDown(); + } + + public function dataTestVcards() { + return [ + // classic vcard + ['BEGIN:VCARD'.PHP_EOL. + 'VERSION:3.0'.PHP_EOL. + 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL. + 'UID:Test'.PHP_EOL. + 'FN:Test'.PHP_EOL. + 'N:Test;;;;'.PHP_EOL. + 'END:VCARD', 'Test'], + + // UID as url + ['BEGIN:VCARD'.PHP_EOL. + 'VERSION:3.0'.PHP_EOL. + 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL. + 'UID:https://User@old.domain.com/remote.php/carddav/addressbooks/User/contacts/2EAF6525-17ADC861-38D6BB1D.vcf'.PHP_EOL. + 'FN:Test'.PHP_EOL. + 'N:Test;;;;'.PHP_EOL. + 'END:VCARD', 'https://User@old.domain.com/remote.php/carddav/addressbooks/User/contacts/2EAF6525-17ADC861-38D6BB1D.vcf'], + + // No uid + ['BEGIN:VCARD'.PHP_EOL. + 'VERSION:3.0'.PHP_EOL. + 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL. + 'FN:Test'.PHP_EOL. + 'N:Test;;;;'.PHP_EOL. + 'END:VCARD', false] + ]; + } + + /** + * @dataProvider dataTestVcards + * + * @param string $from + * @param string|boolean $expected + */ + public function testExtractUIDFromVcard($from, $expected) { + $uid = $this->invokePrivate($this->repair, 'getUid', ['carddata' => $from]); + $this->assertEquals($expected, $uid); + } + + public function shouldRunDataProvider() { + return [ + ['11.0.0.0', true], + ['15.0.0.3', false], + ['13.0.5.2', true], + ['12.0.0.0', true], + ['16.0.0.1', false], + ['15.0.0.2', true], + ['13.0.0.0', true], + ['13.0.0.1', true] + ]; + } + + /** + * @dataProvider shouldRunDataProvider + * + * @param string $from + * @param boolean $expected + */ + public function testShouldRun($from, $expected) { + $this->config->expects($this->any()) + ->method('getSystemValue') + ->with('version', '0.0.0.0') + ->willReturn($from); + + $this->assertEquals($expected, $this->invokePrivate($this->repair, 'shouldRun')); + } + +} diff --git a/tests/lib/Settings/Admin/SharingTest.php b/tests/lib/Settings/Admin/SharingTest.php index 79065fb8d21..c97f22e54b6 100644 --- a/tests/lib/Settings/Admin/SharingTest.php +++ b/tests/lib/Settings/Admin/SharingTest.php @@ -28,6 +28,7 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\Constants; use OCP\IConfig; use OCP\IL10N; +use OCP\Share\IManager; use Test\TestCase; class SharingTest extends TestCase { @@ -37,15 +38,19 @@ class SharingTest extends TestCase { private $config; /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ private $l10n; + /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ + private $shareManager; public function setUp() { parent::setUp(); $this->config = $this->getMockBuilder(IConfig::class)->getMock(); $this->l10n = $this->getMockBuilder(IL10N::class)->getMock(); + $this->shareManager = $this->getMockBuilder(IManager::class)->getMock(); $this->admin = new Sharing( $this->config, - $this->l10n + $this->l10n, + $this->shareManager ); } diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php index 19f37160627..578225840b6 100644 --- a/tests/lib/Share20/DefaultShareProviderTest.php +++ b/tests/lib/Share20/DefaultShareProviderTest.php @@ -363,6 +363,7 @@ class DefaultShareProviderTest extends \Test\TestCase { ->values([ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK), 'password' => $qb->expr()->literal('password'), + 'password_by_talk' => $qb->expr()->literal(true), 'uid_owner' => $qb->expr()->literal('shareOwner'), 'uid_initiator' => $qb->expr()->literal('sharedBy'), 'item_type' => $qb->expr()->literal('file'), @@ -392,6 +393,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType()); $this->assertNull($share->getSharedWith()); $this->assertEquals('password', $share->getPassword()); + $this->assertEquals(true, $share->getSendPasswordByTalk()); $this->assertEquals('sharedBy', $share->getSharedBy()); $this->assertEquals('shareOwner', $share->getShareOwner()); $this->assertEquals($ownerPath, $share->getNode()); @@ -775,6 +777,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $share->setNode($path); $share->setPermissions(1); $share->setPassword('password'); + $share->setSendPasswordByTalk(true); $share->setToken('token'); $expireDate = new \DateTime(); $share->setExpirationDate($expireDate); @@ -792,6 +795,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime()); $this->assertSame($path, $share2->getNode()); $this->assertSame('password', $share2->getPassword()); + $this->assertSame(true, $share2->getSendPasswordByTalk()); $this->assertSame('token', $share2->getToken()); $this->assertEquals($expireDate->getTimestamp(), $share2->getExpirationDate()->getTimestamp()); } @@ -803,6 +807,7 @@ class DefaultShareProviderTest extends \Test\TestCase { ->values([ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK), 'password' => $qb->expr()->literal('password'), + 'password_by_talk' => $qb->expr()->literal(true), 'uid_owner' => $qb->expr()->literal('shareOwner'), 'uid_initiator' => $qb->expr()->literal('sharedBy'), 'item_type' => $qb->expr()->literal('file'), @@ -825,6 +830,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('sharedBy', $share->getSharedBy()); $this->assertSame('secrettoken', $share->getToken()); $this->assertSame('password', $share->getPassword()); + $this->assertSame(true, $share->getSendPasswordByTalk()); $this->assertSame(null, $share->getSharedWith()); } @@ -1788,6 +1794,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('user4', $share2->getSharedBy()); $this->assertSame('user5', $share2->getShareOwner()); $this->assertSame(1, $share2->getPermissions()); + + $share2 = $this->provider->getShareById($id); + + $this->assertEquals($id, $share2->getId()); + $this->assertSame('user3', $share2->getSharedWith()); + $this->assertSame('user4', $share2->getSharedBy()); + $this->assertSame('user5', $share2->getShareOwner()); + $this->assertSame(1, $share2->getPermissions()); } public function testUpdateLink() { @@ -1825,6 +1839,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $share = $this->provider->getShareById($id); $share->setPassword('password'); + $share->setSendPasswordByTalk(true); $share->setSharedBy('user4'); $share->setShareOwner('user5'); $share->setNode($file2); @@ -1833,7 +1848,17 @@ class DefaultShareProviderTest extends \Test\TestCase { $share2 = $this->provider->update($share); $this->assertEquals($id, $share2->getId()); - $this->assertEquals('password', $share->getPassword()); + $this->assertEquals('password', $share2->getPassword()); + $this->assertSame(true, $share2->getSendPasswordByTalk()); + $this->assertSame('user4', $share2->getSharedBy()); + $this->assertSame('user5', $share2->getShareOwner()); + $this->assertSame(1, $share2->getPermissions()); + + $share2 = $this->provider->getShareById($id); + + $this->assertEquals($id, $share2->getId()); + $this->assertEquals('password', $share2->getPassword()); + $this->assertSame(true, $share2->getSendPasswordByTalk()); $this->assertSame('user4', $share2->getSharedBy()); $this->assertSame('user5', $share2->getShareOwner()); $this->assertSame(1, $share2->getPermissions()); @@ -1843,6 +1868,12 @@ class DefaultShareProviderTest extends \Test\TestCase { $id = $this->addShareToDB(\OCP\Share::SHARE_TYPE_LINK, 'foo', 'user1', 'user2', 'file', 42, 'target', 31, null, null); + $qb = $this->dbConn->getQueryBuilder(); + $qb->update('share'); + $qb->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); + $qb->set('password', $qb->createNamedParameter('password')); + $this->assertEquals(1, $qb->execute()); + $users = []; for($i = 0; $i < 6; $i++) { $user = $this->createMock(IUser::class); @@ -1882,7 +1913,15 @@ class DefaultShareProviderTest extends \Test\TestCase { $share2 = $this->provider->update($share); $this->assertEquals($id, $share2->getId()); - $this->assertEquals(null, $share->getPassword()); + $this->assertEquals(null, $share2->getPassword()); + $this->assertSame('user4', $share2->getSharedBy()); + $this->assertSame('user5', $share2->getShareOwner()); + $this->assertSame(1, $share2->getPermissions()); + + $share2 = $this->provider->getShareById($id); + + $this->assertEquals($id, $share2->getId()); + $this->assertEquals(null, $share2->getPassword()); $this->assertSame('user4', $share2->getSharedBy()); $this->assertSame('user5', $share2->getShareOwner()); $this->assertSame(1, $share2->getPermissions()); @@ -1949,6 +1988,15 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('user4', $share2->getSharedBy()); $this->assertSame('user5', $share2->getShareOwner()); $this->assertSame(1, $share2->getPermissions()); + + $share2 = $this->provider->getShareById($id); + + $this->assertEquals($id, $share2->getId()); + // Group shares do not allow updating the recipient + $this->assertSame('group0', $share2->getSharedWith()); + $this->assertSame('user4', $share2->getSharedBy()); + $this->assertSame('user5', $share2->getShareOwner()); + $this->assertSame(1, $share2->getPermissions()); } public function testUpdateGroupSubShares() { @@ -2019,6 +2067,15 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('user5', $share2->getShareOwner()); $this->assertSame(1, $share2->getPermissions()); + $share2 = $this->provider->getShareById($id); + + $this->assertEquals($id, $share2->getId()); + // Group shares do not allow updating the recipient + $this->assertSame('group0', $share2->getSharedWith()); + $this->assertSame('user4', $share2->getSharedBy()); + $this->assertSame('user5', $share2->getShareOwner()); + $this->assertSame(1, $share2->getPermissions()); + $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->select('*') ->from('share') diff --git a/tests/lib/UpdaterTest.php b/tests/lib/UpdaterTest.php index 02fea9c3c0a..afc9f9b1f86 100644 --- a/tests/lib/UpdaterTest.php +++ b/tests/lib/UpdaterTest.php @@ -24,7 +24,6 @@ namespace Test; use OC\Installer; use OC\Updater; -use OCP\BackgroundJob\IJobList; use OCP\IConfig; use OCP\ILogger; use OC\IntegrityCheck\Checker; @@ -40,8 +39,6 @@ class UpdaterTest extends TestCase { private $checker; /** @var Installer|\PHPUnit_Framework_MockObject_MockObject */ private $installer; - /** @var IJobList|\PHPUnit_Framework_MockObject_MockObject */ - private $jobList; public function setUp() { parent::setUp(); @@ -57,16 +54,12 @@ class UpdaterTest extends TestCase { $this->installer = $this->getMockBuilder(Installer::class) ->disableOriginalConstructor() ->getMock(); - $this->jobList = $this->getMockBuilder(IJobList::class) - ->disableOriginalConstructor() - ->getMock(); $this->updater = new Updater( $this->config, $this->checker, $this->logger, - $this->installer, - $this->jobList + $this->installer ); } diff --git a/version.php b/version.php index c3740f01fa3..235e18bf61d 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(15, 0, 0, 1); +$OC_Version = array(15, 0, 0, 3); // The human readable string $OC_VersionString = '15.0.0 alpha'; |