From 890c538c3b3ad3e27586b812c92666090363f757 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Thu, 23 Jun 2016 10:48:20 +0200 Subject: [PATCH 01/81] Add mysql job to CI --- .drone.yml | 14 ++++++++++++++ autotest.sh | 16 ++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.drone.yml b/.drone.yml index 4d0a0aba2a809..df58c126a058c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,6 +17,13 @@ build: - git submodule update --init - ./occ maintenance:install --database-name oc_autotest --database-user oc_autotest --admin-user admin --admin-pass admin --database sqlite --database-pass='' - ./autotest.sh sqlite + mysql: + image: morrisjobke/nextcloud-ci-php7:1.0.4 + commands: + - sleep 10 # gives the database enough time to initialize + - rm -rf data/* config/config.php # TODO: remove this - temporary fix for CI issues + - git submodule update --init + - ./autotest.sh mysql postgres: image: morrisjobke/nextcloud-ci-php7:1.0 commands: @@ -33,3 +40,10 @@ compose: environment: - POSTGRES_USER=oc_autotest - POSTGRES_PASSWORD=oc_autotest + mysql: + image: mysql + environment: + - MYSQL_ROOT_PASSWORD=owncloud + - MYSQL_USER=oc_autotest + - MYSQL_PASSWORD=owncloud + - MYSQL_DATABASE=oc_autotest diff --git a/autotest.sh b/autotest.sh index 4dda2be43e54f..b56394dc9dfe6 100755 --- a/autotest.sh +++ b/autotest.sh @@ -200,12 +200,16 @@ function execute_tests { echo "MySQL is up." else - if [ "mysql" != "$(mysql --version | grep -o mysql)" ] ; then - echo "Your mysql binary is not provided by mysql" - echo "To use the docker container set the USEDOCKER environment variable" - exit -1 - fi - mysql -u "$DATABASEUSER" -powncloud -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true + if [ -z "$DRONE" ] ; then # no need to drop the DB when we are on CI + if [ "mysql" != "$(mysql --version | grep -o mysql)" ] ; then + echo "Your mysql binary is not provided by mysql" + echo "To use the docker container set the USEDOCKER environment variable" + exit -1 + fi + mysql -u "$DATABASEUSER" -powncloud -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true + else + DATABASEHOST=127.0.0.1 + fi fi fi if [ "$DB" == "mariadb" ] ; then From 189d27dae67967374c6483de52a79694230575a5 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Thu, 23 Jun 2016 17:05:31 +0200 Subject: [PATCH 02/81] fix mysql error handling --- .gitmodules | 2 +- 3rdparty | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index bc2beee81adcc..ce19da40ee647 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "3rdparty"] path = 3rdparty - url = https://github.com/owncloud/3rdparty.git + url = https://github.com/nextcloud/3rdparty.git diff --git a/3rdparty b/3rdparty index 509385e674563..46668812ff12d 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 509385e674563e48a977bf8285c826963835528e +Subproject commit 46668812ff12d320ba207f120bd50acffa6e7748 From e2a28db2b505979d4d18a77f9a9d2361cdc078eb Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 23 Jun 2016 18:26:01 +0200 Subject: [PATCH 03/81] Use OC.Backbone instead of Backbone directly in authtoken JS code Fixes asset pipeline issue with the auth token in personal page --- settings/js/authtoken.js | 6 +++--- settings/js/authtoken_collection.js | 6 +++--- settings/js/authtoken_view.js | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/settings/js/authtoken.js b/settings/js/authtoken.js index 215192d7163b3..1d958a4d67531 100644 --- a/settings/js/authtoken.js +++ b/settings/js/authtoken.js @@ -20,14 +20,14 @@ * */ -(function(OC, Backbone) { +(function(OC) { 'use strict'; OC.Settings = OC.Settings || {}; - var AuthToken = Backbone.Model.extend({ + var AuthToken = OC.Backbone.Model.extend({ }); OC.Settings.AuthToken = AuthToken; -})(OC, Backbone); +})(OC); diff --git a/settings/js/authtoken_collection.js b/settings/js/authtoken_collection.js index a78e053995fc8..ab7f7d5804a90 100644 --- a/settings/js/authtoken_collection.js +++ b/settings/js/authtoken_collection.js @@ -20,12 +20,12 @@ * */ -(function(OC, Backbone) { +(function(OC) { 'use strict'; OC.Settings = OC.Settings || {}; - var AuthTokenCollection = Backbone.Collection.extend({ + var AuthTokenCollection = OC.Backbone.Collection.extend({ model: OC.Settings.AuthToken, @@ -49,4 +49,4 @@ OC.Settings.AuthTokenCollection = AuthTokenCollection; -})(OC, Backbone); +})(OC); diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index da5861689a0d6..bfafee8243fc0 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -1,4 +1,4 @@ -/* global Backbone, Handlebars, moment */ +/* global Handlebars, moment */ /** * @author Christoph Wurst @@ -20,7 +20,7 @@ * */ -(function(OC, _, Backbone, $, Handlebars, moment) { +(function(OC, _, $, Handlebars, moment) { 'use strict'; OC.Settings = OC.Settings || {}; @@ -32,7 +32,7 @@ + '' + ''; - var SubView = Backbone.View.extend({ + var SubView = OC.Backbone.View.extend({ collection: null, /** @@ -94,7 +94,7 @@ } }); - var AuthTokenView = Backbone.View.extend({ + var AuthTokenView = OC.Backbone.View.extend({ collection: null, _views: [], @@ -237,4 +237,4 @@ OC.Settings.AuthTokenView = AuthTokenView; -})(OC, _, Backbone, $, Handlebars, moment); +})(OC, _, $, Handlebars, moment); From 8fef9a197f80af6aa161ef07ba088c154c4372e5 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 23 Jun 2016 18:30:45 +0200 Subject: [PATCH 04/81] Remove tooltip when disconnecting token --- settings/js/authtoken_view.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index da5861689a0d6..61ca2f947451c 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -220,6 +220,8 @@ var destroyingToken = token.destroy(); + $row.find('.icon-delete').tooltip('hide'); + var _this = this; $.when(destroyingToken).fail(function() { OC.Notification.showTemporary(t('core', 'Error while deleting the token')); From 2ca13014943858e22daa20c7147121f47f1fed00 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 23 Jun 2016 15:43:21 +0200 Subject: [PATCH 05/81] Add explicit delete permission to link shares Link shares always allowed deletion, however internally the permissions were stored as 7 which lacked delete permissions. This created an inconsistency in the Webdav permissions. This fix makes sure we include delete permissions in the share permissions, which now become 15. In case a client is still passing 7 for legacy reasons, it gets converted automatically to 15. --- apps/files_sharing/lib/API/Share20OCS.php | 21 ++++- .../tests/API/Share20OCSTest.php | 77 ++++++++++++++++--- apps/files_sharing/tests/ApiTest.php | 16 +++- build/integration/features/sharing-v1.feature | 6 +- core/js/sharedialoglinkshareview.js | 2 +- lib/private/Share20/Manager.php | 7 +- tests/lib/Share20/ManagerTest.php | 18 ----- 7 files changed, 103 insertions(+), 44 deletions(-) diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/API/Share20OCS.php index 53b27aae0b8fa..436b8d15ac8f9 100644 --- a/apps/files_sharing/lib/API/Share20OCS.php +++ b/apps/files_sharing/lib/API/Share20OCS.php @@ -354,7 +354,8 @@ public function createShare() { $share->setPermissions( \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | - \OCP\Constants::PERMISSION_UPDATE + \OCP\Constants::PERMISSION_UPDATE | + \OCP\Constants::PERMISSION_DELETE ); } else { $share->setPermissions(\OCP\Constants::PERMISSION_READ); @@ -591,7 +592,7 @@ public function updateShare($id) { $newPermissions = null; if ($publicUpload === 'true') { - $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; + $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; } else if ($publicUpload === 'false') { $newPermissions = \OCP\Constants::PERMISSION_READ; } @@ -602,12 +603,21 @@ public function updateShare($id) { if ($newPermissions !== null && $newPermissions !== \OCP\Constants::PERMISSION_READ && - $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { + // legacy + $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) && + // correct + $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) + ) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); } - if ($newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { + if ( + // legacy + $newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) || + // correct + $newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) + ) { if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); @@ -617,6 +627,9 @@ public function updateShare($id) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); } + + // normalize to correct public upload permissions + $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; } if ($newPermissions !== null) { diff --git a/apps/files_sharing/tests/API/Share20OCSTest.php b/apps/files_sharing/tests/API/Share20OCSTest.php index b760a0f47a014..6435c992f25c1 100644 --- a/apps/files_sharing/tests/API/Share20OCSTest.php +++ b/apps/files_sharing/tests/API/Share20OCSTest.php @@ -1035,7 +1035,7 @@ public function testCreateShareLinkPublicUploadFolder() { $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 | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && + $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && $share->getSharedBy() === 'currentUser' && $share->getPassword() === null && $share->getExpirationDate() === null; @@ -1366,7 +1366,7 @@ public function testUpdateLinkShareSet() { $date = new \DateTime('2000-01-01'); $date->setTime(0,0,0); - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE && \OCP\Constants::PERMISSION_DELETE && + 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; }) @@ -1379,6 +1379,44 @@ public function testUpdateLinkShareSet() { $this->assertEquals($expected->getData(), $result->getData()); } + /** + * @dataProvider publicUploadParamsProvider + */ + public function testUpdateLinkShareEnablePublicUpload($params) { + $ocs = $this->mockFormatShare(); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap($params)); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + $this->shareManager->method('getSharedWith')->willReturn([]); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) { + return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) && + $share->getPassword() === 'password' && + $share->getExpirationDate() === null; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + public function testUpdateLinkShareInvalidDate() { $ocs = $this->mockFormatShare(); @@ -1408,7 +1446,30 @@ public function testUpdateLinkShareInvalidDate() { $this->assertEquals($expected->getData(), $result->getData()); } - public function testUpdateLinkSharePublicUploadNotAllowed() { + public function publicUploadParamsProvider() { + return [ + [[ + ['publicUpload', null, 'true'], + ['expireDate', '', null], + ['password', '', 'password'], + ]], [[ + // legacy had no delete + ['permissions', null, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE], + ['expireDate', '', null], + ['password', '', 'password'], + ]], [[ + // correct + ['permissions', null, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE], + ['expireDate', '', null], + ['password', '', 'password'], + ]], + ]; + } + + /** + * @dataProvider publicUploadParamsProvider + */ + public function testUpdateLinkSharePublicUploadNotAllowed($params) { $ocs = $this->mockFormatShare(); $folder = $this->getMock('\OCP\Files\Folder'); @@ -1421,11 +1482,7 @@ public function testUpdateLinkSharePublicUploadNotAllowed() { $this->request ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'true'], - ['expireDate', '', null], - ['password', '', 'password'], - ])); + ->will($this->returnValueMap($params)); $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false); @@ -1585,7 +1642,7 @@ public function testUpdateLinkSharePublicUploadDoesNotChangeOther() { $this->shareManager->expects($this->once())->method('updateShare')->with( $this->callback(function (\OCP\Share\IShare $share) use ($date) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && + 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; }) @@ -1625,7 +1682,7 @@ public function testUpdateLinkSharePermissions() { $this->shareManager->expects($this->once())->method('updateShare')->with( $this->callback(function (\OCP\Share\IShare $share) use ($date) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && + 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; }) diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index 058b0c4758c46..40c9085353ceb 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -257,7 +257,13 @@ public function testCreateShareLinkPublicUpload() { $this->assertTrue($result->succeeded()); $data = $result->getData(); - $this->assertEquals(7, $data['permissions']); + $this->assertEquals( + \OCP\Constants::PERMISSION_READ | + \OCP\Constants::PERMISSION_CREATE | + \OCP\Constants::PERMISSION_UPDATE | + \OCP\Constants::PERMISSION_DELETE, + $data['permissions'] + ); $this->assertEmpty($data['expiration']); $this->assertTrue(is_string($data['token'])); @@ -1081,7 +1087,13 @@ function testUpdateShareUpload() { $this->assertTrue($result->succeeded()); $share1 = $this->shareManager->getShareById($share1->getFullId()); - $this->assertEquals(7, $share1->getPermissions()); + $this->assertEquals( + \OCP\Constants::PERMISSION_READ | + \OCP\Constants::PERMISSION_CREATE | + \OCP\Constants::PERMISSION_UPDATE | + \OCP\Constants::PERMISSION_DELETE, + $share1->getPermissions() + ); // cleanup $this->shareManager->deleteShare($share1); diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 79dc1326f3c1e..3878e741f60e2 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -61,7 +61,7 @@ Feature: sharing And the HTTP status code should be "200" And Share fields of last share match with | id | A_NUMBER | - | permissions | 7 | + | permissions | 15 | | expiration | +3 days | | url | AN_URL | | token | A_TOKEN | @@ -159,7 +159,7 @@ Feature: sharing | share_type | 3 | | file_source | A_NUMBER | | file_target | /FOLDER | - | permissions | 7 | + | permissions | 15 | | stime | A_NUMBER | | token | A_TOKEN | | storage | A_NUMBER | @@ -189,7 +189,7 @@ Feature: sharing | share_type | 3 | | file_source | A_NUMBER | | file_target | /FOLDER | - | permissions | 7 | + | permissions | 15 | | stime | A_NUMBER | | token | A_TOKEN | | storage | A_NUMBER | diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 817c3408e7e98..59f7ffcae036b 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -202,7 +202,7 @@ var permissions = OC.PERMISSION_READ; if($checkbox.is(':checked')) { - permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ; + permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE; } this.model.saveLinkShare({ diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index e2730f4d5fb0e..2c08e616f82a9 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -446,14 +446,9 @@ protected function linkCreateChecks(\OCP\Share\IShare $share) { throw new \InvalidArgumentException('Link shares can\'t have reshare permissions'); } - // We don't allow deletion on link shares - if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) { - throw new \InvalidArgumentException('Link shares can\'t have delete permissions'); - } - // Check if public upload is allowed if (!$this->shareApiLinkAllowPublicUpload() && - ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE))) { + ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) { throw new \InvalidArgumentException('Public upload not allowed'); } } diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index a50ea6c892ad4..d2539f8577cbb 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -1318,24 +1318,6 @@ public function testLinkCreateChecksSharePermissions() { $this->invokePrivate($this->manager, 'linkCreateChecks', [$share]); } - /** - * @expectedException Exception - * @expectedExceptionMessage Link shares can't have delete permissions - */ - public function testLinkCreateChecksDeletePermissions() { - $share = $this->manager->newShare(); - - $share->setPermissions(\OCP\Constants::PERMISSION_DELETE); - - $this->config - ->method('getAppValue') - ->will($this->returnValueMap([ - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ])); - - $this->invokePrivate($this->manager, 'linkCreateChecks', [$share]); - } - /** * @expectedException Exception * @expectedExceptionMessage Public upload not allowed From 7dc36289ab4df280ea9412932cec403b62aa30a8 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 23 Jun 2016 16:37:03 +0200 Subject: [PATCH 06/81] Repair step to adjust link share delete permissions --- lib/private/Repair/RepairInvalidShares.php | 23 ++++++ tests/lib/Repair/RepairInvalidSharesTest.php | 87 ++++++++++++++++++++ version.php | 2 +- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php index 30f67a1f39460..728632486d013 100644 --- a/lib/private/Repair/RepairInvalidShares.php +++ b/lib/private/Repair/RepairInvalidShares.php @@ -71,6 +71,25 @@ private function removeExpirationDateFromNonLinkShares(IOutput $out) { } } + /** + * In the past link shares with public upload enabled were missing the delete permission. + */ + private function addShareLinkDeletePermission(IOutput $out) { + $oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; + $newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; + $builder = $this->connection->getQueryBuilder(); + $builder + ->update('share') + ->set('permissions', $builder->expr()->literal($newPerms)) + ->where($builder->expr()->eq('share_type', $builder->expr()->literal(\OC\Share\Constants::SHARE_TYPE_LINK))) + ->andWhere($builder->expr()->eq('permissions', $builder->expr()->literal($oldPerms))); + + $updatedEntries = $builder->execute(); + if ($updatedEntries > 0) { + $out->info('Fixed link share permissions for ' . $updatedEntries . ' shares'); + } + } + /** * Remove shares where the parent share does not exist anymore */ @@ -113,6 +132,10 @@ public function run(IOutput $out) { // this situation was only possible before 8.2 $this->removeExpirationDateFromNonLinkShares($out); } + if (version_compare($ocVersionFromBeforeUpdate, '9.1.0.9', '<')) { + // this situation was only possible before 9.1 + $this->addShareLinkDeletePermission($out); + } $this->removeSharesNonExistingParent($out); } diff --git a/tests/lib/Repair/RepairInvalidSharesTest.php b/tests/lib/Repair/RepairInvalidSharesTest.php index a1e871bcc80c0..1ac42e53bf6ab 100644 --- a/tests/lib/Repair/RepairInvalidSharesTest.php +++ b/tests/lib/Repair/RepairInvalidSharesTest.php @@ -123,6 +123,93 @@ public function testRemoveExpirationDateForNonLinkShares() { $this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there'); } + /** + * Test remove expiration date for non-link shares + */ + public function testAddShareLinkDeletePermission() { + $oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; + $newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; + + // share with old permissions + $qb = $this->connection->getQueryBuilder(); + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK), + 'uid_owner' => $qb->expr()->literal('user1'), + 'item_type' => $qb->expr()->literal('folder'), + 'item_source' => $qb->expr()->literal(123), + 'item_target' => $qb->expr()->literal('/123'), + 'file_source' => $qb->expr()->literal(123), + 'file_target' => $qb->expr()->literal('/test'), + 'permissions' => $qb->expr()->literal($oldPerms), + 'stime' => $qb->expr()->literal(time()), + ]) + ->execute(); + + $bogusShareId = $this->getLastShareId(); + + // share with read-only permissions + $qb = $this->connection->getQueryBuilder(); + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK), + 'uid_owner' => $qb->expr()->literal('user1'), + 'item_type' => $qb->expr()->literal('folder'), + 'item_source' => $qb->expr()->literal(123), + 'item_target' => $qb->expr()->literal('/123'), + 'file_source' => $qb->expr()->literal(123), + 'file_target' => $qb->expr()->literal('/test'), + 'permissions' => $qb->expr()->literal(\OCP\Constants::PERMISSION_READ), + 'stime' => $qb->expr()->literal(time()), + ]) + ->execute(); + + $keepThisShareId = $this->getLastShareId(); + + // user share to keep + $qb = $this->connection->getQueryBuilder(); + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER), + 'share_with' => $qb->expr()->literal('recipientuser1'), + 'uid_owner' => $qb->expr()->literal('user1'), + 'item_type' => $qb->expr()->literal('folder'), + 'item_source' => $qb->expr()->literal(123), + 'item_target' => $qb->expr()->literal('/123'), + 'file_source' => $qb->expr()->literal(123), + 'file_target' => $qb->expr()->literal('/test'), + 'permissions' => $qb->expr()->literal(3), + 'stime' => $qb->expr()->literal(time()), + ]) + ->execute(); + + $keepThisShareId2 = $this->getLastShareId(); + + /** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */ + $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput') + ->disableOriginalConstructor() + ->getMock(); + + $this->repair->run($outputMock); + + $results = $this->connection->getQueryBuilder() + ->select('*') + ->from('share') + ->orderBy('permissions', 'ASC') + ->execute() + ->fetchAll(); + + $this->assertCount(3, $results); + + $untouchedShare = $results[0]; + $untouchedShare2 = $results[1]; + $updatedShare = $results[2]; + $this->assertEquals($keepThisShareId, $untouchedShare['id'], 'sanity check'); + $this->assertEquals($keepThisShareId2, $untouchedShare2['id'], 'sanity check'); + $this->assertEquals($bogusShareId, $updatedShare['id'], 'sanity check'); + $this->assertEquals($newPerms, $updatedShare['permissions'], 'delete permission was added'); + } + /** * Test remove shares where the parent share does not exist anymore */ diff --git a/version.php b/version.php index 3015d976e5301..b439ffbbdad85 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(9, 1, 0, 9); +$OC_Version = array(9, 1, 0, 10); // The human readable string $OC_VersionString = '9.1.0 beta 2'; From d345047b0f34d436d15fb91dd9b2aac91f8dc845 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 24 Jun 2016 10:24:41 +0200 Subject: [PATCH 07/81] Make code integrity check work when OC is not installed yet --- lib/private/IntegrityCheck/Checker.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php index ab68f75220636..57127f280c4f9 100644 --- a/lib/private/IntegrityCheck/Checker.php +++ b/lib/private/IntegrityCheck/Checker.php @@ -108,7 +108,11 @@ public function isCodeCheckEnforced() { * applicable for very specific scenarios and we should not advertise it * too prominent. So please do not add it to config.sample.php. */ - $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false); + if ($this->config !== null) { + $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false); + } else { + $isIntegrityCheckDisabled = false; + } if($isIntegrityCheckDisabled === true) { return false; } @@ -401,7 +405,10 @@ public function getResults() { return json_decode($cachedResults, true); } - return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true); + if ($this->config !== null) { + return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true); + } + return []; } /** @@ -416,7 +423,9 @@ private function storeResults($scope, array $result) { if(!empty($result)) { $resultArray[$scope] = $result; } - $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray)); + if ($this->config !== null) { + $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray)); + } $this->cache->set(self::CACHE_KEY, json_encode($resultArray)); } From 5e58b5115fb5e014c01954253573e160bd1c5f22 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 23 Jun 2016 11:27:02 +0200 Subject: [PATCH 08/81] Prerender file list pages to include search results When filtering the file list, if a result is on an unrendered page, make sure to call _nextPage() to prerender the pages in order to display all matching results. --- apps/files/js/filelist.js | 22 ++++++++++++++++++---- apps/files/tests/js/filelistSpec.js | 11 +++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index f249f2d35c928..18f17a7207c27 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -2351,22 +2351,36 @@ * @param filter */ setFilter:function(filter) { + var total = 0; this._filter = filter; this.fileSummary.setFilter(filter, this.files); + total = this.fileSummary.getTotal(); if (!this.$el.find('.mask').exists()) { this.hideIrrelevantUIWhenNoFilesMatch(); } var that = this; + var visibleCount = 0; filter = filter.toLowerCase(); - this.$fileList.find('tr').each(function(i,e) { - var $e = $(e); + + function filterRows(tr) { + var $e = $(tr); if ($e.data('file').toString().toLowerCase().indexOf(filter) === -1) { $e.addClass('hidden'); } else { + visibleCount++; $e.removeClass('hidden'); } - }); - that.$container.trigger('scroll'); + } + + var $trs = this.$fileList.find('tr'); + do { + _.each($trs, filterRows); + if (visibleCount < total) { + $trs = this._nextPage(false); + } + } while (visibleCount < total); + + this.$container.trigger('scroll'); }, hideIrrelevantUIWhenNoFilesMatch:function() { if (this._filter && this.fileSummary.summary.totalDirs + this.fileSummary.summary.totalFiles === 0) { diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 7e6408128bbca..a74e1c7328c7b 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -989,6 +989,17 @@ describe('OCA.Files.FileList tests', function() { expect($summary.find('.info').text()).toEqual("1 folder and 3 files"); expect($nofilterresults.hasClass('hidden')).toEqual(true); }); + it('filters the list of non-rendered rows using filter()', function() { + var $summary = $('#filestable .summary'); + var $nofilterresults = fileList.$el.find(".nofilterresults"); + fileList.setFiles(generateFiles(0, 64)); + + fileList.setFilter('63'); + expect($('#fileList tr:not(.hidden)').length).toEqual(1); + expect($summary.hasClass('hidden')).toEqual(false); + expect($summary.find('.info').text()).toEqual("0 folders and 1 file matches '63'"); + expect($nofilterresults.hasClass('hidden')).toEqual(true); + }); it('hides the emptyfiles notice when using filter()', function() { expect(fileList.files.length).toEqual(0); expect(fileList.files).toEqual([]); From db34671626e1172624f369433da76bb7d41faf24 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Fri, 24 Jun 2016 13:57:09 +0200 Subject: [PATCH 09/81] check login name when authenticating with client token --- lib/private/User/Session.php | 13 +++++++++++-- tests/lib/User/SessionTest.php | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 2b65f31af2891..6219a89e5b3b0 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -280,7 +280,7 @@ public function getLoginName() { */ public function login($uid, $password) { $this->session->regenerateId(); - if ($this->validateToken($password)) { + if ($this->validateToken($password, $uid)) { // When logging in with token, the password must be decrypted first before passing to login hook try { $token = $this->tokenProvider->getToken($password); @@ -584,15 +584,24 @@ private function checkTokenCredentials(IToken $dbToken, $token) { * Invalidates the token if checks fail * * @param string $token + * @param string $user login name * @return boolean */ - private function validateToken($token) { + private function validateToken($token, $user = null) { try { $dbToken = $this->tokenProvider->getToken($token); } catch (InvalidTokenException $ex) { return false; } + // Check if login names match + if (!is_null($user) && $dbToken->getLoginName() !== $user) { + // TODO: this makes it imposssible to use different login names on browser and client + // e.g. login by e-mail 'user@example.com' on browser for generating the token will not + // allow to use the client token with the login name 'user'. + return false; + } + if (!$this->checkTokenCredentials($dbToken, $token)) { return false; } diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php index eef4c7ff5ea63..447c6142f3414 100644 --- a/tests/lib/User/SessionTest.php +++ b/tests/lib/User/SessionTest.php @@ -314,6 +314,36 @@ public function testLoginNonExisting() { $userSession->login('foo', 'bar'); } + /** + * When using a device token, the loginname must match the one that was used + * when generating the token on the browser. + */ + public function testLoginWithDifferentTokenLoginName() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $manager = $this->getMock('\OC\User\Manager'); + $backend = $this->getMock('\Test\Util\User\Dummy'); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $username = 'user123'; + $token = new \OC\Authentication\Token\DefaultToken(); + $token->setLoginName($username); + + $session->expects($this->never()) + ->method('set'); + $session->expects($this->once()) + ->method('regenerateId'); + $this->tokenProvider->expects($this->once()) + ->method('getToken') + ->with('bar') + ->will($this->returnValue($token)); + + $manager->expects($this->once()) + ->method('checkPassword') + ->with('foo', 'bar') + ->will($this->returnValue(false)); + + $userSession->login('foo', 'bar'); + } + /** * @expectedException \OC\Authentication\Exceptions\PasswordLoginForbiddenException */ From d484fef837601724764a268f5d955bbbaaa52e69 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Fri, 24 Jun 2016 15:31:48 +0200 Subject: [PATCH 10/81] show which login name to use for the new app password --- settings/Controller/AuthSettingsController.php | 1 + settings/js/authtoken_view.js | 6 ++++++ settings/templates/personal.php | 1 + 3 files changed, 8 insertions(+) diff --git a/settings/Controller/AuthSettingsController.php b/settings/Controller/AuthSettingsController.php index fba663b034de2..db2db6e5bfc70 100644 --- a/settings/Controller/AuthSettingsController.php +++ b/settings/Controller/AuthSettingsController.php @@ -118,6 +118,7 @@ public function create($name) { return [ 'token' => $token, + 'loginName' => $loginName, 'deviceToken' => $deviceToken ]; } diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index da5861689a0d6..cf6b4f7c8d41f 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -107,6 +107,8 @@ _result: undefined, + _newAppLoginName: undefined, + _newAppPassword: undefined, _hideAppPasswordBtn: undefined, @@ -136,6 +138,7 @@ this._addAppPasswordBtn.click(_.bind(this._addAppPassword, this)); this._result = $('#app-password-result'); + this._newAppLoginName = $('#new-app-login-name'); this._newAppPassword = $('#new-app-password'); this._newAppPassword.on('focus', _.bind(this._onNewTokenFocus, this)); this._hideAppPasswordBtn = $('#app-password-hide'); @@ -181,6 +184,9 @@ $.when(creatingToken).done(function(resp) { _this.collection.add(resp.deviceToken); _this.render(); + _this._newAppLoginName.text(t('core', 'You may now configure your client with username "{loginName}" and the following password:', { + loginName: resp.loginName + })); _this._newAppPassword.val(resp.token); _this._toggleFormResult(false); _this._newAppPassword.select(); diff --git a/settings/templates/personal.php b/settings/templates/personal.php index b9b8429d943c4..19a9968cec718 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -203,6 +203,7 @@ From 19a53982d47b45e8498186c6fbd7cab85cbdfd8e Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 24 Jun 2016 16:46:25 +0200 Subject: [PATCH 11/81] Keep encryption enabled if decrypting for single user When decrypting all files of a single user, the admin usually does not intend encryption to be suddenly disabled for everyone. This fix reenables encryption after decrypting for a single user. Decrypting for all users will still disable encryption globally. --- core/Command/Encryption/DecryptAll.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/Command/Encryption/DecryptAll.php b/core/Command/Encryption/DecryptAll.php index 83c6c1dc1689d..cda7853b8b40f 100644 --- a/core/Command/Encryption/DecryptAll.php +++ b/core/Command/Encryption/DecryptAll.php @@ -150,6 +150,9 @@ protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln(' aborted.'); $output->writeln('Server side encryption remains enabled'); $this->config->setAppValue('core', 'encryption_enabled', 'yes'); + } else if ($uid !== '') { + $output->writeln('Server side encryption remains enabled'); + $this->config->setAppValue('core', 'encryption_enabled', 'yes'); } $this->resetSingleUserAndTrashbin(); } else { From 213d7119f9159d42a3877ed5c2e5a033dfd24979 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Fri, 24 Jun 2016 17:00:59 +0200 Subject: [PATCH 12/81] fix layout --- settings/css/settings.css | 8 ++++++++ settings/js/authtoken_view.js | 9 ++++++--- settings/templates/personal.php | 13 ++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/settings/css/settings.css b/settings/css/settings.css index e4ddec9152a64..914c0d7515da9 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -131,11 +131,19 @@ table.nostyle td { padding: 0.2em 0; } opacity: 0.6; } +#new-app-login-name, #new-app-password { width: 186px; font-family: monospace; background-color: lightyellow; } +.app-password-row { + display: table-row; +} +.app-password-label { + display: table-cell; + padding-right: 1em; +} /* USERS */ #newgroup-init a span { margin-left: 20px; } diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index cf6b4f7c8d41f..db6dac85ce023 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -139,6 +139,7 @@ this._result = $('#app-password-result'); this._newAppLoginName = $('#new-app-login-name'); + this._newAppLoginName.on('focus', _.bind(this._onNewTokenLoginNameFocus, this)); this._newAppPassword = $('#new-app-password'); this._newAppPassword.on('focus', _.bind(this._onNewTokenFocus, this)); this._hideAppPasswordBtn = $('#app-password-hide'); @@ -184,9 +185,7 @@ $.when(creatingToken).done(function(resp) { _this.collection.add(resp.deviceToken); _this.render(); - _this._newAppLoginName.text(t('core', 'You may now configure your client with username "{loginName}" and the following password:', { - loginName: resp.loginName - })); + _this._newAppLoginName.val(resp.loginName); _this._newAppPassword.val(resp.token); _this._toggleFormResult(false); _this._newAppPassword.select(); @@ -200,6 +199,10 @@ }); }, + _onNewTokenLoginNameFocus: function() { + this._newAppLoginName.select(); + }, + _onNewTokenFocus: function() { this._newAppPassword.select(); }, diff --git a/settings/templates/personal.php b/settings/templates/personal.php index 19a9968cec718..50e7ef79f8b93 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -203,9 +203,16 @@ From 2acf8313b0b9b549740e294c19319dafb0cd4387 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 6 Jun 2016 17:40:38 +0200 Subject: [PATCH 13/81] initial commit for the theming app --- .gitignore | 1 + apps/theming/appinfo/app.php | 23 +++++++++++++++++++ apps/theming/appinfo/info.xml | 15 +++++++++++++ apps/theming/css/settings-admin.css | 0 apps/theming/js/settings-admin.js | 20 +++++++++++++++++ apps/theming/settings/settings-admin.php | 27 +++++++++++++++++++++++ apps/theming/templates/settings-admin.php | 11 +++++++++ 7 files changed, 97 insertions(+) create mode 100644 apps/theming/appinfo/app.php create mode 100644 apps/theming/appinfo/info.xml create mode 100644 apps/theming/css/settings-admin.css create mode 100644 apps/theming/js/settings-admin.js create mode 100644 apps/theming/settings/settings-admin.php create mode 100644 apps/theming/templates/settings-admin.php diff --git a/.gitignore b/.gitignore index 69b977aee03cf..215682c408106 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ !/apps/testing !/apps/admin_audit !/apps/updatenotification +!/apps/theming /apps/files_external/3rdparty/irodsphp/PHPUnitTest /apps/files_external/3rdparty/irodsphp/web /apps/files_external/3rdparty/irodsphp/prods/test diff --git a/apps/theming/appinfo/app.php b/apps/theming/appinfo/app.php new file mode 100644 index 0000000000000..97db0e568b1b2 --- /dev/null +++ b/apps/theming/appinfo/app.php @@ -0,0 +1,23 @@ + + * + * @copyright Copyright (c) 2016, Bjoern Schiessle + * @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 as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your opinion) 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 + * + */ + +\OCP\App::registerAdmin('theming', 'settings/settings-admin'); \ No newline at end of file diff --git a/apps/theming/appinfo/info.xml b/apps/theming/appinfo/info.xml new file mode 100644 index 0000000000000..f0f2fb80afe96 --- /dev/null +++ b/apps/theming/appinfo/info.xml @@ -0,0 +1,15 @@ + + + theming + Theming + Adjust the Nextcloud theme + AGPL + Bjoern Schiessle + 0.1.0 + Theming + other + + + + + diff --git a/apps/theming/css/settings-admin.css b/apps/theming/css/settings-admin.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js new file mode 100644 index 0000000000000..317773a32c2c4 --- /dev/null +++ b/apps/theming/js/settings-admin.js @@ -0,0 +1,20 @@ +/** + * @author Björn Schießle + * + * @copyright Copyright (c) 2016, Bjoern Schiessle + * @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 as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your opinion) 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 + * + */ diff --git a/apps/theming/settings/settings-admin.php b/apps/theming/settings/settings-admin.php new file mode 100644 index 0000000000000..8c7effb31071f --- /dev/null +++ b/apps/theming/settings/settings-admin.php @@ -0,0 +1,27 @@ + + * + * @copyright Copyright (c) 2016, Bjoern Schiessle + * @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 as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your opinion) 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 + * + */ + +\OC_Util::checkAdminUser(); + +$template = new OCP\Template('theming', 'settings-admin'); + +return $template->fetchPage(); diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php new file mode 100644 index 0000000000000..4177f59d07178 --- /dev/null +++ b/apps/theming/templates/settings-admin.php @@ -0,0 +1,11 @@ + +
+

t('Theming')); ?>

+ Hello World +
+ From 55f3a659c4304649d2a6f70513eb3e874ebb18bd Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Tue, 7 Jun 2016 19:09:49 +0200 Subject: [PATCH 14/81] basic information architecture for the theming app --- apps/theming/css/settings-admin.css | 3 +++ apps/theming/templates/settings-admin.php | 20 +++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/theming/css/settings-admin.css b/apps/theming/css/settings-admin.css index e69de29bb2d1d..c058953545e3e 100644 --- a/apps/theming/css/settings-admin.css +++ b/apps/theming/css/settings-admin.css @@ -0,0 +1,3 @@ +#theming input { + width: 17em; +} diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index 4177f59d07178..82d21751abc4e 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -4,8 +4,22 @@ script('theming', 'settings-admin'); style('theming', 'settings-admin') ?> -
+

t('Theming')); ?>

- Hello World -
+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
From a1f171287ff681485d7021e97bcd1701db558551 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 9 Jun 2016 21:46:30 +0200 Subject: [PATCH 15/81] write theme settings to database --- apps/theming/appinfo/app.php | 2 +- apps/theming/appinfo/routes.php | 42 + apps/theming/css/settings-admin.css | 21 + apps/theming/js/3rdparty/jscolor/LICENSE.txt | 674 ++++++ apps/theming/js/3rdparty/jscolor/jscolor.js | 1844 +++++++++++++++++ .../js/3rdparty/jscolor/jscolor.min.js | 10 + apps/theming/js/settings-admin.js | 83 + .../lib/controller/themingcontroller.php | 86 + apps/theming/lib/init.php | 94 + apps/theming/lib/template.php | 172 ++ apps/theming/settings/settings-admin.php | 33 + apps/theming/templates/settings-admin.php | 29 +- lib/private/legacy/defaults.php | 37 +- 13 files changed, 3115 insertions(+), 12 deletions(-) create mode 100644 apps/theming/appinfo/routes.php create mode 100644 apps/theming/js/3rdparty/jscolor/LICENSE.txt create mode 100644 apps/theming/js/3rdparty/jscolor/jscolor.js create mode 100644 apps/theming/js/3rdparty/jscolor/jscolor.min.js create mode 100644 apps/theming/lib/controller/themingcontroller.php create mode 100644 apps/theming/lib/init.php create mode 100644 apps/theming/lib/template.php diff --git a/apps/theming/appinfo/app.php b/apps/theming/appinfo/app.php index 97db0e568b1b2..ed7ea3e20f8d6 100644 --- a/apps/theming/appinfo/app.php +++ b/apps/theming/appinfo/app.php @@ -20,4 +20,4 @@ * */ -\OCP\App::registerAdmin('theming', 'settings/settings-admin'); \ No newline at end of file +\OCP\App::registerAdmin('theming', 'settings/settings-admin'); diff --git a/apps/theming/appinfo/routes.php b/apps/theming/appinfo/routes.php new file mode 100644 index 0000000000000..7a2ff1f9dbd4d --- /dev/null +++ b/apps/theming/appinfo/routes.php @@ -0,0 +1,42 @@ + + * + * @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 . + * + */ + + +namespace OCA\Theming\AppInfo; + +(new \OCP\AppFramework\App('theming'))->registerRoutes($this, array('routes' => array( + [ + 'name' => 'Theming#updateStylesheet', + 'url' => '/ajax/updateStylesheet', + 'verb' => 'POST' + ], + [ + 'name' => 'Theming#undo', + 'url' => '/ajax/undoChanges', + 'verb' => 'POST' + ], + [ + 'name' => 'Theming#updateLogo', + 'url' => '/ajax/updateLogo', + 'verb' => 'POST' + ], +))); + diff --git a/apps/theming/css/settings-admin.css b/apps/theming/css/settings-admin.css index c058953545e3e..b0739465ef246 100644 --- a/apps/theming/css/settings-admin.css +++ b/apps/theming/css/settings-admin.css @@ -1,3 +1,24 @@ #theming input { width: 17em; } + +#theming .upload-logo-field { + display: none; +} + +#theming .theme-undo { + cursor: pointer; +} + +#theming .icon { + display: inline-block; +} + +#theming .theming-label { + min-width: 6em; + display: inline-block; +} + +#theming .icon-upload { + display: inline-flex; +} diff --git a/apps/theming/js/3rdparty/jscolor/LICENSE.txt b/apps/theming/js/3rdparty/jscolor/LICENSE.txt new file mode 100644 index 0000000000000..94a9ed024d385 --- /dev/null +++ b/apps/theming/js/3rdparty/jscolor/LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/apps/theming/js/3rdparty/jscolor/jscolor.js b/apps/theming/js/3rdparty/jscolor/jscolor.js new file mode 100644 index 0000000000000..2bdd4607b41c7 --- /dev/null +++ b/apps/theming/js/3rdparty/jscolor/jscolor.js @@ -0,0 +1,1844 @@ +/** + * jscolor - JavaScript Color Picker + * + * @link http://jscolor.com + * @license For open source use: GPLv3 + * For commercial use: JSColor Commercial License + * @author Jan Odvarko + * @version 2.0.4 + * + * See usage examples at http://jscolor.com/examples/ + */ + + +"use strict"; + + +if (!window.jscolor) { window.jscolor = (function () { + + +var jsc = { + + + register : function () { + jsc.attachDOMReadyEvent(jsc.init); + jsc.attachEvent(document, 'mousedown', jsc.onDocumentMouseDown); + jsc.attachEvent(document, 'touchstart', jsc.onDocumentTouchStart); + jsc.attachEvent(window, 'resize', jsc.onWindowResize); + }, + + + init : function () { + if (jsc.jscolor.lookupClass) { + jsc.jscolor.installByClassName(jsc.jscolor.lookupClass); + } + }, + + + tryInstallOnElements : function (elms, className) { + var matchClass = new RegExp('(^|\\s)(' + className + ')(\\s*(\\{[^}]*\\})|\\s|$)', 'i'); + + for (var i = 0; i < elms.length; i += 1) { + if (elms[i].type !== undefined && elms[i].type.toLowerCase() == 'color') { + if (jsc.isColorAttrSupported) { + // skip inputs of type 'color' if supported by the browser + continue; + } + } + var m; + if (!elms[i].jscolor && elms[i].className && (m = elms[i].className.match(matchClass))) { + var targetElm = elms[i]; + var optsStr = null; + + var dataOptions = jsc.getDataAttr(targetElm, 'jscolor'); + if (dataOptions !== null) { + optsStr = dataOptions; + } else if (m[4]) { + optsStr = m[4]; + } + + var opts = {}; + if (optsStr) { + try { + opts = (new Function ('return (' + optsStr + ')'))(); + } catch(eParseError) { + jsc.warn('Error parsing jscolor options: ' + eParseError + ':\n' + optsStr); + } + } + targetElm.jscolor = new jsc.jscolor(targetElm, opts); + } + } + }, + + + isColorAttrSupported : (function () { + var elm = document.createElement('input'); + if (elm.setAttribute) { + elm.setAttribute('type', 'color'); + if (elm.type.toLowerCase() == 'color') { + return true; + } + } + return false; + })(), + + + isCanvasSupported : (function () { + var elm = document.createElement('canvas'); + return !!(elm.getContext && elm.getContext('2d')); + })(), + + + fetchElement : function (mixed) { + return typeof mixed === 'string' ? document.getElementById(mixed) : mixed; + }, + + + isElementType : function (elm, type) { + return elm.nodeName.toLowerCase() === type.toLowerCase(); + }, + + + getDataAttr : function (el, name) { + var attrName = 'data-' + name; + var attrValue = el.getAttribute(attrName); + if (attrValue !== null) { + return attrValue; + } + return null; + }, + + + attachEvent : function (el, evnt, func) { + if (el.addEventListener) { + el.addEventListener(evnt, func, false); + } else if (el.attachEvent) { + el.attachEvent('on' + evnt, func); + } + }, + + + detachEvent : function (el, evnt, func) { + if (el.removeEventListener) { + el.removeEventListener(evnt, func, false); + } else if (el.detachEvent) { + el.detachEvent('on' + evnt, func); + } + }, + + + _attachedGroupEvents : {}, + + + attachGroupEvent : function (groupName, el, evnt, func) { + if (!jsc._attachedGroupEvents.hasOwnProperty(groupName)) { + jsc._attachedGroupEvents[groupName] = []; + } + jsc._attachedGroupEvents[groupName].push([el, evnt, func]); + jsc.attachEvent(el, evnt, func); + }, + + + detachGroupEvents : function (groupName) { + if (jsc._attachedGroupEvents.hasOwnProperty(groupName)) { + for (var i = 0; i < jsc._attachedGroupEvents[groupName].length; i += 1) { + var evt = jsc._attachedGroupEvents[groupName][i]; + jsc.detachEvent(evt[0], evt[1], evt[2]); + } + delete jsc._attachedGroupEvents[groupName]; + } + }, + + + attachDOMReadyEvent : function (func) { + var fired = false; + var fireOnce = function () { + if (!fired) { + fired = true; + func(); + } + }; + + if (document.readyState === 'complete') { + setTimeout(fireOnce, 1); // async + return; + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireOnce, false); + + // Fallback + window.addEventListener('load', fireOnce, false); + + } else if (document.attachEvent) { + // IE + document.attachEvent('onreadystatechange', function () { + if (document.readyState === 'complete') { + document.detachEvent('onreadystatechange', arguments.callee); + fireOnce(); + } + }) + + // Fallback + window.attachEvent('onload', fireOnce); + + // IE7/8 + if (document.documentElement.doScroll && window == window.top) { + var tryScroll = function () { + if (!document.body) { return; } + try { + document.documentElement.doScroll('left'); + fireOnce(); + } catch (e) { + setTimeout(tryScroll, 1); + } + }; + tryScroll(); + } + } + }, + + + warn : function (msg) { + if (window.console && window.console.warn) { + window.console.warn(msg); + } + }, + + + preventDefault : function (e) { + if (e.preventDefault) { e.preventDefault(); } + e.returnValue = false; + }, + + + captureTarget : function (target) { + // IE + if (target.setCapture) { + jsc._capturedTarget = target; + jsc._capturedTarget.setCapture(); + } + }, + + + releaseTarget : function () { + // IE + if (jsc._capturedTarget) { + jsc._capturedTarget.releaseCapture(); + jsc._capturedTarget = null; + } + }, + + + fireEvent : function (el, evnt) { + if (!el) { + return; + } + if (document.createEvent) { + var ev = document.createEvent('HTMLEvents'); + ev.initEvent(evnt, true, true); + el.dispatchEvent(ev); + } else if (document.createEventObject) { + var ev = document.createEventObject(); + el.fireEvent('on' + evnt, ev); + } else if (el['on' + evnt]) { // alternatively use the traditional event model + el['on' + evnt](); + } + }, + + + classNameToList : function (className) { + return className.replace(/^\s+|\s+$/g, '').split(/\s+/); + }, + + + // The className parameter (str) can only contain a single class name + hasClass : function (elm, className) { + if (!className) { + return false; + } + return -1 != (' ' + elm.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + className + ' '); + }, + + + // The className parameter (str) can contain multiple class names separated by whitespace + setClass : function (elm, className) { + var classList = jsc.classNameToList(className); + for (var i = 0; i < classList.length; i += 1) { + if (!jsc.hasClass(elm, classList[i])) { + elm.className += (elm.className ? ' ' : '') + classList[i]; + } + } + }, + + + // The className parameter (str) can contain multiple class names separated by whitespace + unsetClass : function (elm, className) { + var classList = jsc.classNameToList(className); + for (var i = 0; i < classList.length; i += 1) { + var repl = new RegExp( + '^\\s*' + classList[i] + '\\s*|' + + '\\s*' + classList[i] + '\\s*$|' + + '\\s+' + classList[i] + '(\\s+)', + 'g' + ); + elm.className = elm.className.replace(repl, '$1'); + } + }, + + + getStyle : function (elm) { + return window.getComputedStyle ? window.getComputedStyle(elm) : elm.currentStyle; + }, + + + setStyle : (function () { + var helper = document.createElement('div'); + var getSupportedProp = function (names) { + for (var i = 0; i < names.length; i += 1) { + if (names[i] in helper.style) { + return names[i]; + } + } + }; + var props = { + borderRadius: getSupportedProp(['borderRadius', 'MozBorderRadius', 'webkitBorderRadius']), + boxShadow: getSupportedProp(['boxShadow', 'MozBoxShadow', 'webkitBoxShadow']) + }; + return function (elm, prop, value) { + switch (prop.toLowerCase()) { + case 'opacity': + var alphaOpacity = Math.round(parseFloat(value) * 100); + elm.style.opacity = value; + elm.style.filter = 'alpha(opacity=' + alphaOpacity + ')'; + break; + default: + elm.style[props[prop]] = value; + break; + } + }; + })(), + + + setBorderRadius : function (elm, value) { + jsc.setStyle(elm, 'borderRadius', value || '0'); + }, + + + setBoxShadow : function (elm, value) { + jsc.setStyle(elm, 'boxShadow', value || 'none'); + }, + + + getElementPos : function (e, relativeToViewport) { + var x=0, y=0; + var rect = e.getBoundingClientRect(); + x = rect.left; + y = rect.top; + if (!relativeToViewport) { + var viewPos = jsc.getViewPos(); + x += viewPos[0]; + y += viewPos[1]; + } + return [x, y]; + }, + + + getElementSize : function (e) { + return [e.offsetWidth, e.offsetHeight]; + }, + + + // get pointer's X/Y coordinates relative to viewport + getAbsPointerPos : function (e) { + if (!e) { e = window.event; } + var x = 0, y = 0; + if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) { + // touch devices + x = e.changedTouches[0].clientX; + y = e.changedTouches[0].clientY; + } else if (typeof e.clientX === 'number') { + x = e.clientX; + y = e.clientY; + } + return { x: x, y: y }; + }, + + + // get pointer's X/Y coordinates relative to target element + getRelPointerPos : function (e) { + if (!e) { e = window.event; } + var target = e.target || e.srcElement; + var targetRect = target.getBoundingClientRect(); + + var x = 0, y = 0; + + var clientX = 0, clientY = 0; + if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) { + // touch devices + clientX = e.changedTouches[0].clientX; + clientY = e.changedTouches[0].clientY; + } else if (typeof e.clientX === 'number') { + clientX = e.clientX; + clientY = e.clientY; + } + + x = clientX - targetRect.left; + y = clientY - targetRect.top; + return { x: x, y: y }; + }, + + + getViewPos : function () { + var doc = document.documentElement; + return [ + (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0), + (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0) + ]; + }, + + + getViewSize : function () { + var doc = document.documentElement; + return [ + (window.innerWidth || doc.clientWidth), + (window.innerHeight || doc.clientHeight), + ]; + }, + + + redrawPosition : function () { + + if (jsc.picker && jsc.picker.owner) { + var thisObj = jsc.picker.owner; + + var tp, vp; + + if (thisObj.fixed) { + // Fixed elements are positioned relative to viewport, + // therefore we can ignore the scroll offset + tp = jsc.getElementPos(thisObj.targetElement, true); // target pos + vp = [0, 0]; // view pos + } else { + tp = jsc.getElementPos(thisObj.targetElement); // target pos + vp = jsc.getViewPos(); // view pos + } + + var ts = jsc.getElementSize(thisObj.targetElement); // target size + var vs = jsc.getViewSize(); // view size + var ps = jsc.getPickerOuterDims(thisObj); // picker size + var a, b, c; + switch (thisObj.position.toLowerCase()) { + case 'left': a=1; b=0; c=-1; break; + case 'right':a=1; b=0; c=1; break; + case 'top': a=0; b=1; c=-1; break; + default: a=0; b=1; c=1; break; + } + var l = (ts[b]+ps[b])/2; + + // compute picker position + if (!thisObj.smartPosition) { + var pp = [ + tp[a], + tp[b]+ts[b]-l+l*c + ]; + } else { + var pp = [ + -vp[a]+tp[a]+ps[a] > vs[a] ? + (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) : + tp[a], + -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ? + (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) : + (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c) + ]; + } + + var x = pp[a]; + var y = pp[b]; + var positionValue = thisObj.fixed ? 'fixed' : 'absolute'; + var contractShadow = + (pp[0] + ps[0] > tp[0] || pp[0] < tp[0] + ts[0]) && + (pp[1] + ps[1] < tp[1] + ts[1]); + + jsc._drawPosition(thisObj, x, y, positionValue, contractShadow); + } + }, + + + _drawPosition : function (thisObj, x, y, positionValue, contractShadow) { + var vShadow = contractShadow ? 0 : thisObj.shadowBlur; // px + + jsc.picker.wrap.style.position = positionValue; + jsc.picker.wrap.style.left = x + 'px'; + jsc.picker.wrap.style.top = y + 'px'; + + jsc.setBoxShadow( + jsc.picker.boxS, + thisObj.shadow ? + new jsc.BoxShadow(0, vShadow, thisObj.shadowBlur, 0, thisObj.shadowColor) : + null); + }, + + + getPickerDims : function (thisObj) { + var displaySlider = !!jsc.getSliderComponent(thisObj); + var dims = [ + 2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.width + + (displaySlider ? 2 * thisObj.insetWidth + jsc.getPadToSliderPadding(thisObj) + thisObj.sliderSize : 0), + 2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.height + + (thisObj.closable ? 2 * thisObj.insetWidth + thisObj.padding + thisObj.buttonHeight : 0) + ]; + return dims; + }, + + + getPickerOuterDims : function (thisObj) { + var dims = jsc.getPickerDims(thisObj); + return [ + dims[0] + 2 * thisObj.borderWidth, + dims[1] + 2 * thisObj.borderWidth + ]; + }, + + + getPadToSliderPadding : function (thisObj) { + return Math.max(thisObj.padding, 1.5 * (2 * thisObj.pointerBorderWidth + thisObj.pointerThickness)); + }, + + + getPadYComponent : function (thisObj) { + switch (thisObj.mode.charAt(1).toLowerCase()) { + case 'v': return 'v'; break; + } + return 's'; + }, + + + getSliderComponent : function (thisObj) { + if (thisObj.mode.length > 2) { + switch (thisObj.mode.charAt(2).toLowerCase()) { + case 's': return 's'; break; + case 'v': return 'v'; break; + } + } + return null; + }, + + + onDocumentMouseDown : function (e) { + if (!e) { e = window.event; } + var target = e.target || e.srcElement; + + if (target._jscLinkedInstance) { + if (target._jscLinkedInstance.showOnClick) { + target._jscLinkedInstance.show(); + } + } else if (target._jscControlName) { + jsc.onControlPointerStart(e, target, target._jscControlName, 'mouse'); + } else { + // Mouse is outside the picker controls -> hide the color picker! + if (jsc.picker && jsc.picker.owner) { + jsc.picker.owner.hide(); + } + } + }, + + + onDocumentTouchStart : function (e) { + if (!e) { e = window.event; } + var target = e.target || e.srcElement; + + if (target._jscLinkedInstance) { + if (target._jscLinkedInstance.showOnClick) { + target._jscLinkedInstance.show(); + } + } else if (target._jscControlName) { + jsc.onControlPointerStart(e, target, target._jscControlName, 'touch'); + } else { + if (jsc.picker && jsc.picker.owner) { + jsc.picker.owner.hide(); + } + } + }, + + + onWindowResize : function (e) { + jsc.redrawPosition(); + }, + + + onParentScroll : function (e) { + // hide the picker when one of the parent elements is scrolled + if (jsc.picker && jsc.picker.owner) { + jsc.picker.owner.hide(); + } + }, + + + _pointerMoveEvent : { + mouse: 'mousemove', + touch: 'touchmove' + }, + _pointerEndEvent : { + mouse: 'mouseup', + touch: 'touchend' + }, + + + _pointerOrigin : null, + _capturedTarget : null, + + + onControlPointerStart : function (e, target, controlName, pointerType) { + var thisObj = target._jscInstance; + + jsc.preventDefault(e); + jsc.captureTarget(target); + + var registerDragEvents = function (doc, offset) { + jsc.attachGroupEvent('drag', doc, jsc._pointerMoveEvent[pointerType], + jsc.onDocumentPointerMove(e, target, controlName, pointerType, offset)); + jsc.attachGroupEvent('drag', doc, jsc._pointerEndEvent[pointerType], + jsc.onDocumentPointerEnd(e, target, controlName, pointerType)); + }; + + registerDragEvents(document, [0, 0]); + + if (window.parent && window.frameElement) { + var rect = window.frameElement.getBoundingClientRect(); + var ofs = [-rect.left, -rect.top]; + registerDragEvents(window.parent.window.document, ofs); + } + + var abs = jsc.getAbsPointerPos(e); + var rel = jsc.getRelPointerPos(e); + jsc._pointerOrigin = { + x: abs.x - rel.x, + y: abs.y - rel.y + }; + + switch (controlName) { + case 'pad': + // if the slider is at the bottom, move it up + switch (jsc.getSliderComponent(thisObj)) { + case 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); }; break; + case 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); }; break; + } + jsc.setPad(thisObj, e, 0, 0); + break; + + case 'sld': + jsc.setSld(thisObj, e, 0); + break; + } + + jsc.dispatchFineChange(thisObj); + }, + + + onDocumentPointerMove : function (e, target, controlName, pointerType, offset) { + return function (e) { + var thisObj = target._jscInstance; + switch (controlName) { + case 'pad': + if (!e) { e = window.event; } + jsc.setPad(thisObj, e, offset[0], offset[1]); + jsc.dispatchFineChange(thisObj); + break; + + case 'sld': + if (!e) { e = window.event; } + jsc.setSld(thisObj, e, offset[1]); + jsc.dispatchFineChange(thisObj); + break; + } + } + }, + + + onDocumentPointerEnd : function (e, target, controlName, pointerType) { + return function (e) { + var thisObj = target._jscInstance; + jsc.detachGroupEvents('drag'); + jsc.releaseTarget(); + // Always dispatch changes after detaching outstanding mouse handlers, + // in case some user interaction will occur in user's onchange callback + // that would intrude with current mouse events + jsc.dispatchChange(thisObj); + }; + }, + + + dispatchChange : function (thisObj) { + if (thisObj.valueElement) { + if (jsc.isElementType(thisObj.valueElement, 'input')) { + jsc.fireEvent(thisObj.valueElement, 'change'); + } + } + }, + + + dispatchFineChange : function (thisObj) { + if (thisObj.onFineChange) { + var callback; + if (typeof thisObj.onFineChange === 'string') { + callback = new Function (thisObj.onFineChange); + } else { + callback = thisObj.onFineChange; + } + callback.call(thisObj); + } + }, + + + setPad : function (thisObj, e, ofsX, ofsY) { + var pointerAbs = jsc.getAbsPointerPos(e); + var x = ofsX + pointerAbs.x - jsc._pointerOrigin.x - thisObj.padding - thisObj.insetWidth; + var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth; + + var xVal = x * (360 / (thisObj.width - 1)); + var yVal = 100 - (y * (100 / (thisObj.height - 1))); + + switch (jsc.getPadYComponent(thisObj)) { + case 's': thisObj.fromHSV(xVal, yVal, null, jsc.leaveSld); break; + case 'v': thisObj.fromHSV(xVal, null, yVal, jsc.leaveSld); break; + } + }, + + + setSld : function (thisObj, e, ofsY) { + var pointerAbs = jsc.getAbsPointerPos(e); + var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth; + + var yVal = 100 - (y * (100 / (thisObj.height - 1))); + + switch (jsc.getSliderComponent(thisObj)) { + case 's': thisObj.fromHSV(null, yVal, null, jsc.leavePad); break; + case 'v': thisObj.fromHSV(null, null, yVal, jsc.leavePad); break; + } + }, + + + _vmlNS : 'jsc_vml_', + _vmlCSS : 'jsc_vml_css_', + _vmlReady : false, + + + initVML : function () { + if (!jsc._vmlReady) { + // init VML namespace + var doc = document; + if (!doc.namespaces[jsc._vmlNS]) { + doc.namespaces.add(jsc._vmlNS, 'urn:schemas-microsoft-com:vml'); + } + if (!doc.styleSheets[jsc._vmlCSS]) { + var tags = ['shape', 'shapetype', 'group', 'background', 'path', 'formulas', 'handles', 'fill', 'stroke', 'shadow', 'textbox', 'textpath', 'imagedata', 'line', 'polyline', 'curve', 'rect', 'roundrect', 'oval', 'arc', 'image']; + var ss = doc.createStyleSheet(); + ss.owningElement.id = jsc._vmlCSS; + for (var i = 0; i < tags.length; i += 1) { + ss.addRule(jsc._vmlNS + '\\:' + tags[i], 'behavior:url(#default#VML);'); + } + } + jsc._vmlReady = true; + } + }, + + + createPalette : function () { + + var paletteObj = { + elm: null, + draw: null + }; + + if (jsc.isCanvasSupported) { + // Canvas implementation for modern browsers + + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + + var drawFunc = function (width, height, type) { + canvas.width = width; + canvas.height = height; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + var hGrad = ctx.createLinearGradient(0, 0, canvas.width, 0); + hGrad.addColorStop(0 / 6, '#F00'); + hGrad.addColorStop(1 / 6, '#FF0'); + hGrad.addColorStop(2 / 6, '#0F0'); + hGrad.addColorStop(3 / 6, '#0FF'); + hGrad.addColorStop(4 / 6, '#00F'); + hGrad.addColorStop(5 / 6, '#F0F'); + hGrad.addColorStop(6 / 6, '#F00'); + + ctx.fillStyle = hGrad; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + var vGrad = ctx.createLinearGradient(0, 0, 0, canvas.height); + switch (type.toLowerCase()) { + case 's': + vGrad.addColorStop(0, 'rgba(255,255,255,0)'); + vGrad.addColorStop(1, 'rgba(255,255,255,1)'); + break; + case 'v': + vGrad.addColorStop(0, 'rgba(0,0,0,0)'); + vGrad.addColorStop(1, 'rgba(0,0,0,1)'); + break; + } + ctx.fillStyle = vGrad; + ctx.fillRect(0, 0, canvas.width, canvas.height); + }; + + paletteObj.elm = canvas; + paletteObj.draw = drawFunc; + + } else { + // VML fallback for IE 7 and 8 + + jsc.initVML(); + + var vmlContainer = document.createElement('div'); + vmlContainer.style.position = 'relative'; + vmlContainer.style.overflow = 'hidden'; + + var hGrad = document.createElement(jsc._vmlNS + ':fill'); + hGrad.type = 'gradient'; + hGrad.method = 'linear'; + hGrad.angle = '90'; + hGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0' + + var hRect = document.createElement(jsc._vmlNS + ':rect'); + hRect.style.position = 'absolute'; + hRect.style.left = -1 + 'px'; + hRect.style.top = -1 + 'px'; + hRect.stroked = false; + hRect.appendChild(hGrad); + vmlContainer.appendChild(hRect); + + var vGrad = document.createElement(jsc._vmlNS + ':fill'); + vGrad.type = 'gradient'; + vGrad.method = 'linear'; + vGrad.angle = '180'; + vGrad.opacity = '0'; + + var vRect = document.createElement(jsc._vmlNS + ':rect'); + vRect.style.position = 'absolute'; + vRect.style.left = -1 + 'px'; + vRect.style.top = -1 + 'px'; + vRect.stroked = false; + vRect.appendChild(vGrad); + vmlContainer.appendChild(vRect); + + var drawFunc = function (width, height, type) { + vmlContainer.style.width = width + 'px'; + vmlContainer.style.height = height + 'px'; + + hRect.style.width = + vRect.style.width = + (width + 1) + 'px'; + hRect.style.height = + vRect.style.height = + (height + 1) + 'px'; + + // Colors must be specified during every redraw, otherwise IE won't display + // a full gradient during a subsequential redraw + hGrad.color = '#F00'; + hGrad.color2 = '#F00'; + + switch (type.toLowerCase()) { + case 's': + vGrad.color = vGrad.color2 = '#FFF'; + break; + case 'v': + vGrad.color = vGrad.color2 = '#000'; + break; + } + }; + + paletteObj.elm = vmlContainer; + paletteObj.draw = drawFunc; + } + + return paletteObj; + }, + + + createSliderGradient : function () { + + var sliderObj = { + elm: null, + draw: null + }; + + if (jsc.isCanvasSupported) { + // Canvas implementation for modern browsers + + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + + var drawFunc = function (width, height, color1, color2) { + canvas.width = width; + canvas.height = height; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + var grad = ctx.createLinearGradient(0, 0, 0, canvas.height); + grad.addColorStop(0, color1); + grad.addColorStop(1, color2); + + ctx.fillStyle = grad; + ctx.fillRect(0, 0, canvas.width, canvas.height); + }; + + sliderObj.elm = canvas; + sliderObj.draw = drawFunc; + + } else { + // VML fallback for IE 7 and 8 + + jsc.initVML(); + + var vmlContainer = document.createElement('div'); + vmlContainer.style.position = 'relative'; + vmlContainer.style.overflow = 'hidden'; + + var grad = document.createElement(jsc._vmlNS + ':fill'); + grad.type = 'gradient'; + grad.method = 'linear'; + grad.angle = '180'; + + var rect = document.createElement(jsc._vmlNS + ':rect'); + rect.style.position = 'absolute'; + rect.style.left = -1 + 'px'; + rect.style.top = -1 + 'px'; + rect.stroked = false; + rect.appendChild(grad); + vmlContainer.appendChild(rect); + + var drawFunc = function (width, height, color1, color2) { + vmlContainer.style.width = width + 'px'; + vmlContainer.style.height = height + 'px'; + + rect.style.width = (width + 1) + 'px'; + rect.style.height = (height + 1) + 'px'; + + grad.color = color1; + grad.color2 = color2; + }; + + sliderObj.elm = vmlContainer; + sliderObj.draw = drawFunc; + } + + return sliderObj; + }, + + + leaveValue : 1<<0, + leaveStyle : 1<<1, + leavePad : 1<<2, + leaveSld : 1<<3, + + + BoxShadow : (function () { + var BoxShadow = function (hShadow, vShadow, blur, spread, color, inset) { + this.hShadow = hShadow; + this.vShadow = vShadow; + this.blur = blur; + this.spread = spread; + this.color = color; + this.inset = !!inset; + }; + + BoxShadow.prototype.toString = function () { + var vals = [ + Math.round(this.hShadow) + 'px', + Math.round(this.vShadow) + 'px', + Math.round(this.blur) + 'px', + Math.round(this.spread) + 'px', + this.color + ]; + if (this.inset) { + vals.push('inset'); + } + return vals.join(' '); + }; + + return BoxShadow; + })(), + + + // + // Usage: + // var myColor = new jscolor( [, ]) + // + + jscolor : function (targetElement, options) { + + // General options + // + this.value = null; // initial HEX color. To change it later, use methods fromString(), fromHSV() and fromRGB() + this.valueElement = targetElement; // element that will be used to display and input the color code + this.styleElement = targetElement; // element that will preview the picked color using CSS backgroundColor + this.required = true; // whether the associated text can be left empty + this.refine = true; // whether to refine the entered color code (e.g. uppercase it and remove whitespace) + this.hash = false; // whether to prefix the HEX color code with # symbol + this.uppercase = true; // whether to uppercase the color code + this.onFineChange = null; // called instantly every time the color changes (value can be either a function or a string with javascript code) + this.activeClass = 'jscolor-active'; // class to be set to the target element when a picker window is open on it + this.minS = 0; // min allowed saturation (0 - 100) + this.maxS = 100; // max allowed saturation (0 - 100) + this.minV = 0; // min allowed value (brightness) (0 - 100) + this.maxV = 100; // max allowed value (brightness) (0 - 100) + + // Accessing the picked color + // + this.hsv = [0, 0, 100]; // read-only [0-360, 0-100, 0-100] + this.rgb = [255, 255, 255]; // read-only [0-255, 0-255, 0-255] + + // Color Picker options + // + this.width = 181; // width of color palette (in px) + this.height = 101; // height of color palette (in px) + this.showOnClick = true; // whether to display the color picker when user clicks on its target element + this.mode = 'HSV'; // HSV | HVS | HS | HV - layout of the color picker controls + this.position = 'bottom'; // left | right | top | bottom - position relative to the target element + this.smartPosition = true; // automatically change picker position when there is not enough space for it + this.sliderSize = 16; // px + this.crossSize = 8; // px + this.closable = false; // whether to display the Close button + this.closeText = 'Close'; + this.buttonColor = '#000000'; // CSS color + this.buttonHeight = 18; // px + this.padding = 12; // px + this.backgroundColor = '#FFFFFF'; // CSS color + this.borderWidth = 1; // px + this.borderColor = '#BBBBBB'; // CSS color + this.borderRadius = 8; // px + this.insetWidth = 1; // px + this.insetColor = '#BBBBBB'; // CSS color + this.shadow = true; // whether to display shadow + this.shadowBlur = 15; // px + this.shadowColor = 'rgba(0,0,0,0.2)'; // CSS color + this.pointerColor = '#4C4C4C'; // px + this.pointerBorderColor = '#FFFFFF'; // px + this.pointerBorderWidth = 1; // px + this.pointerThickness = 2; // px + this.zIndex = 1000; + this.container = null; // where to append the color picker (BODY element by default) + + + for (var opt in options) { + if (options.hasOwnProperty(opt)) { + this[opt] = options[opt]; + } + } + + + this.hide = function () { + if (isPickerOwner()) { + detachPicker(); + } + }; + + + this.show = function () { + drawPicker(); + }; + + + this.redraw = function () { + if (isPickerOwner()) { + drawPicker(); + } + }; + + + this.importColor = function () { + if (!this.valueElement) { + this.exportColor(); + } else { + if (jsc.isElementType(this.valueElement, 'input')) { + if (!this.refine) { + if (!this.fromString(this.valueElement.value, jsc.leaveValue)) { + if (this.styleElement) { + this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage; + this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor; + this.styleElement.style.color = this.styleElement._jscOrigStyle.color; + } + this.exportColor(jsc.leaveValue | jsc.leaveStyle); + } + } else if (!this.required && /^\s*$/.test(this.valueElement.value)) { + this.valueElement.value = ''; + if (this.styleElement) { + this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage; + this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor; + this.styleElement.style.color = this.styleElement._jscOrigStyle.color; + } + this.exportColor(jsc.leaveValue | jsc.leaveStyle); + + } else if (this.fromString(this.valueElement.value)) { + // managed to import color successfully from the value -> OK, don't do anything + } else { + this.exportColor(); + } + } else { + // not an input element -> doesn't have any value + this.exportColor(); + } + } + }; + + + this.exportColor = function (flags) { + if (!(flags & jsc.leaveValue) && this.valueElement) { + var value = this.toString(); + if (this.uppercase) { value = value.toUpperCase(); } + if (this.hash) { value = '#' + value; } + + if (jsc.isElementType(this.valueElement, 'input')) { + this.valueElement.value = value; + } else { + this.valueElement.innerHTML = value; + } + } + if (!(flags & jsc.leaveStyle)) { + if (this.styleElement) { + this.styleElement.style.backgroundImage = 'none'; + this.styleElement.style.backgroundColor = '#' + this.toString(); + this.styleElement.style.color = this.isLight() ? '#000' : '#FFF'; + } + } + if (!(flags & jsc.leavePad) && isPickerOwner()) { + redrawPad(); + } + if (!(flags & jsc.leaveSld) && isPickerOwner()) { + redrawSld(); + } + }; + + + // h: 0-360 + // s: 0-100 + // v: 0-100 + // + this.fromHSV = function (h, s, v, flags) { // null = don't change + if (h !== null) { + if (isNaN(h)) { return false; } + h = Math.max(0, Math.min(360, h)); + } + if (s !== null) { + if (isNaN(s)) { return false; } + s = Math.max(0, Math.min(100, this.maxS, s), this.minS); + } + if (v !== null) { + if (isNaN(v)) { return false; } + v = Math.max(0, Math.min(100, this.maxV, v), this.minV); + } + + this.rgb = HSV_RGB( + h===null ? this.hsv[0] : (this.hsv[0]=h), + s===null ? this.hsv[1] : (this.hsv[1]=s), + v===null ? this.hsv[2] : (this.hsv[2]=v) + ); + + this.exportColor(flags); + }; + + + // r: 0-255 + // g: 0-255 + // b: 0-255 + // + this.fromRGB = function (r, g, b, flags) { // null = don't change + if (r !== null) { + if (isNaN(r)) { return false; } + r = Math.max(0, Math.min(255, r)); + } + if (g !== null) { + if (isNaN(g)) { return false; } + g = Math.max(0, Math.min(255, g)); + } + if (b !== null) { + if (isNaN(b)) { return false; } + b = Math.max(0, Math.min(255, b)); + } + + var hsv = RGB_HSV( + r===null ? this.rgb[0] : r, + g===null ? this.rgb[1] : g, + b===null ? this.rgb[2] : b + ); + if (hsv[0] !== null) { + this.hsv[0] = Math.max(0, Math.min(360, hsv[0])); + } + if (hsv[2] !== 0) { + this.hsv[1] = hsv[1]===null ? null : Math.max(0, this.minS, Math.min(100, this.maxS, hsv[1])); + } + this.hsv[2] = hsv[2]===null ? null : Math.max(0, this.minV, Math.min(100, this.maxV, hsv[2])); + + // update RGB according to final HSV, as some values might be trimmed + var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]); + this.rgb[0] = rgb[0]; + this.rgb[1] = rgb[1]; + this.rgb[2] = rgb[2]; + + this.exportColor(flags); + }; + + + this.fromString = function (str, flags) { + var m; + if (m = str.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i)) { + // HEX notation + // + + if (m[1].length === 6) { + // 6-char notation + this.fromRGB( + parseInt(m[1].substr(0,2),16), + parseInt(m[1].substr(2,2),16), + parseInt(m[1].substr(4,2),16), + flags + ); + } else { + // 3-char notation + this.fromRGB( + parseInt(m[1].charAt(0) + m[1].charAt(0),16), + parseInt(m[1].charAt(1) + m[1].charAt(1),16), + parseInt(m[1].charAt(2) + m[1].charAt(2),16), + flags + ); + } + return true; + + } else if (m = str.match(/^\W*rgba?\(([^)]*)\)\W*$/i)) { + var params = m[1].split(','); + var re = /^\s*(\d*)(\.\d+)?\s*$/; + var mR, mG, mB; + if ( + params.length >= 3 && + (mR = params[0].match(re)) && + (mG = params[1].match(re)) && + (mB = params[2].match(re)) + ) { + var r = parseFloat((mR[1] || '0') + (mR[2] || '')); + var g = parseFloat((mG[1] || '0') + (mG[2] || '')); + var b = parseFloat((mB[1] || '0') + (mB[2] || '')); + this.fromRGB(r, g, b, flags); + return true; + } + } + return false; + }; + + + this.toString = function () { + return ( + (0x100 | Math.round(this.rgb[0])).toString(16).substr(1) + + (0x100 | Math.round(this.rgb[1])).toString(16).substr(1) + + (0x100 | Math.round(this.rgb[2])).toString(16).substr(1) + ); + }; + + + this.toHEXString = function () { + return '#' + this.toString().toUpperCase(); + }; + + + this.toRGBString = function () { + return ('rgb(' + + Math.round(this.rgb[0]) + ',' + + Math.round(this.rgb[1]) + ',' + + Math.round(this.rgb[2]) + ')' + ); + }; + + + this.isLight = function () { + return ( + 0.213 * this.rgb[0] + + 0.715 * this.rgb[1] + + 0.072 * this.rgb[2] > + 255 / 2 + ); + }; + + + this._processParentElementsInDOM = function () { + if (this._linkedElementsProcessed) { return; } + this._linkedElementsProcessed = true; + + var elm = this.targetElement; + do { + // If the target element or one of its parent nodes has fixed position, + // then use fixed positioning instead + // + // Note: In Firefox, getComputedStyle returns null in a hidden iframe, + // that's why we need to check if the returned style object is non-empty + var currStyle = jsc.getStyle(elm); + if (currStyle && currStyle.position.toLowerCase() === 'fixed') { + this.fixed = true; + } + + if (elm !== this.targetElement) { + // Ensure to attach onParentScroll only once to each parent element + // (multiple targetElements can share the same parent nodes) + // + // Note: It's not just offsetParents that can be scrollable, + // that's why we loop through all parent nodes + if (!elm._jscEventsAttached) { + jsc.attachEvent(elm, 'scroll', jsc.onParentScroll); + elm._jscEventsAttached = true; + } + } + } while ((elm = elm.parentNode) && !jsc.isElementType(elm, 'body')); + }; + + + // r: 0-255 + // g: 0-255 + // b: 0-255 + // + // returns: [ 0-360, 0-100, 0-100 ] + // + function RGB_HSV (r, g, b) { + r /= 255; + g /= 255; + b /= 255; + var n = Math.min(Math.min(r,g),b); + var v = Math.max(Math.max(r,g),b); + var m = v - n; + if (m === 0) { return [ null, 0, 100 * v ]; } + var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m); + return [ + 60 * (h===6?0:h), + 100 * (m/v), + 100 * v + ]; + } + + + // h: 0-360 + // s: 0-100 + // v: 0-100 + // + // returns: [ 0-255, 0-255, 0-255 ] + // + function HSV_RGB (h, s, v) { + var u = 255 * (v / 100); + + if (h === null) { + return [ u, u, u ]; + } + + h /= 60; + s /= 100; + + var i = Math.floor(h); + var f = i%2 ? h-i : 1-(h-i); + var m = u * (1 - s); + var n = u * (1 - s * f); + switch (i) { + case 6: + case 0: return [u,n,m]; + case 1: return [n,u,m]; + case 2: return [m,u,n]; + case 3: return [m,n,u]; + case 4: return [n,m,u]; + case 5: return [u,m,n]; + } + } + + + function detachPicker () { + jsc.unsetClass(THIS.targetElement, THIS.activeClass); + jsc.picker.wrap.parentNode.removeChild(jsc.picker.wrap); + delete jsc.picker.owner; + } + + + function drawPicker () { + + // At this point, when drawing the picker, we know what the parent elements are + // and we can do all related DOM operations, such as registering events on them + // or checking their positioning + THIS._processParentElementsInDOM(); + + if (!jsc.picker) { + jsc.picker = { + owner: null, + wrap : document.createElement('div'), + box : document.createElement('div'), + boxS : document.createElement('div'), // shadow area + boxB : document.createElement('div'), // border + pad : document.createElement('div'), + padB : document.createElement('div'), // border + padM : document.createElement('div'), // mouse/touch area + padPal : jsc.createPalette(), + cross : document.createElement('div'), + crossBY : document.createElement('div'), // border Y + crossBX : document.createElement('div'), // border X + crossLY : document.createElement('div'), // line Y + crossLX : document.createElement('div'), // line X + sld : document.createElement('div'), + sldB : document.createElement('div'), // border + sldM : document.createElement('div'), // mouse/touch area + sldGrad : jsc.createSliderGradient(), + sldPtrS : document.createElement('div'), // slider pointer spacer + sldPtrIB : document.createElement('div'), // slider pointer inner border + sldPtrMB : document.createElement('div'), // slider pointer middle border + sldPtrOB : document.createElement('div'), // slider pointer outer border + btn : document.createElement('div'), + btnT : document.createElement('span') // text + }; + + jsc.picker.pad.appendChild(jsc.picker.padPal.elm); + jsc.picker.padB.appendChild(jsc.picker.pad); + jsc.picker.cross.appendChild(jsc.picker.crossBY); + jsc.picker.cross.appendChild(jsc.picker.crossBX); + jsc.picker.cross.appendChild(jsc.picker.crossLY); + jsc.picker.cross.appendChild(jsc.picker.crossLX); + jsc.picker.padB.appendChild(jsc.picker.cross); + jsc.picker.box.appendChild(jsc.picker.padB); + jsc.picker.box.appendChild(jsc.picker.padM); + + jsc.picker.sld.appendChild(jsc.picker.sldGrad.elm); + jsc.picker.sldB.appendChild(jsc.picker.sld); + jsc.picker.sldB.appendChild(jsc.picker.sldPtrOB); + jsc.picker.sldPtrOB.appendChild(jsc.picker.sldPtrMB); + jsc.picker.sldPtrMB.appendChild(jsc.picker.sldPtrIB); + jsc.picker.sldPtrIB.appendChild(jsc.picker.sldPtrS); + jsc.picker.box.appendChild(jsc.picker.sldB); + jsc.picker.box.appendChild(jsc.picker.sldM); + + jsc.picker.btn.appendChild(jsc.picker.btnT); + jsc.picker.box.appendChild(jsc.picker.btn); + + jsc.picker.boxB.appendChild(jsc.picker.box); + jsc.picker.wrap.appendChild(jsc.picker.boxS); + jsc.picker.wrap.appendChild(jsc.picker.boxB); + } + + var p = jsc.picker; + + var displaySlider = !!jsc.getSliderComponent(THIS); + var dims = jsc.getPickerDims(THIS); + var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize); + var padToSliderPadding = jsc.getPadToSliderPadding(THIS); + var borderRadius = Math.min( + THIS.borderRadius, + Math.round(THIS.padding * Math.PI)); // px + var padCursor = 'crosshair'; + + // wrap + p.wrap.style.clear = 'both'; + p.wrap.style.width = (dims[0] + 2 * THIS.borderWidth) + 'px'; + p.wrap.style.height = (dims[1] + 2 * THIS.borderWidth) + 'px'; + p.wrap.style.zIndex = THIS.zIndex; + + // picker + p.box.style.width = dims[0] + 'px'; + p.box.style.height = dims[1] + 'px'; + + p.boxS.style.position = 'absolute'; + p.boxS.style.left = '0'; + p.boxS.style.top = '0'; + p.boxS.style.width = '100%'; + p.boxS.style.height = '100%'; + jsc.setBorderRadius(p.boxS, borderRadius + 'px'); + + // picker border + p.boxB.style.position = 'relative'; + p.boxB.style.border = THIS.borderWidth + 'px solid'; + p.boxB.style.borderColor = THIS.borderColor; + p.boxB.style.background = THIS.backgroundColor; + jsc.setBorderRadius(p.boxB, borderRadius + 'px'); + + // IE hack: + // If the element is transparent, IE will trigger the event on the elements under it, + // e.g. on Canvas or on elements with border + p.padM.style.background = + p.sldM.style.background = + '#FFF'; + jsc.setStyle(p.padM, 'opacity', '0'); + jsc.setStyle(p.sldM, 'opacity', '0'); + + // pad + p.pad.style.position = 'relative'; + p.pad.style.width = THIS.width + 'px'; + p.pad.style.height = THIS.height + 'px'; + + // pad palettes (HSV and HVS) + p.padPal.draw(THIS.width, THIS.height, jsc.getPadYComponent(THIS)); + + // pad border + p.padB.style.position = 'absolute'; + p.padB.style.left = THIS.padding + 'px'; + p.padB.style.top = THIS.padding + 'px'; + p.padB.style.border = THIS.insetWidth + 'px solid'; + p.padB.style.borderColor = THIS.insetColor; + + // pad mouse area + p.padM._jscInstance = THIS; + p.padM._jscControlName = 'pad'; + p.padM.style.position = 'absolute'; + p.padM.style.left = '0'; + p.padM.style.top = '0'; + p.padM.style.width = (THIS.padding + 2 * THIS.insetWidth + THIS.width + padToSliderPadding / 2) + 'px'; + p.padM.style.height = dims[1] + 'px'; + p.padM.style.cursor = padCursor; + + // pad cross + p.cross.style.position = 'absolute'; + p.cross.style.left = + p.cross.style.top = + '0'; + p.cross.style.width = + p.cross.style.height = + crossOuterSize + 'px'; + + // pad cross border Y and X + p.crossBY.style.position = + p.crossBX.style.position = + 'absolute'; + p.crossBY.style.background = + p.crossBX.style.background = + THIS.pointerBorderColor; + p.crossBY.style.width = + p.crossBX.style.height = + (2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px'; + p.crossBY.style.height = + p.crossBX.style.width = + crossOuterSize + 'px'; + p.crossBY.style.left = + p.crossBX.style.top = + (Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2) - THIS.pointerBorderWidth) + 'px'; + p.crossBY.style.top = + p.crossBX.style.left = + '0'; + + // pad cross line Y and X + p.crossLY.style.position = + p.crossLX.style.position = + 'absolute'; + p.crossLY.style.background = + p.crossLX.style.background = + THIS.pointerColor; + p.crossLY.style.height = + p.crossLX.style.width = + (crossOuterSize - 2 * THIS.pointerBorderWidth) + 'px'; + p.crossLY.style.width = + p.crossLX.style.height = + THIS.pointerThickness + 'px'; + p.crossLY.style.left = + p.crossLX.style.top = + (Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2)) + 'px'; + p.crossLY.style.top = + p.crossLX.style.left = + THIS.pointerBorderWidth + 'px'; + + // slider + p.sld.style.overflow = 'hidden'; + p.sld.style.width = THIS.sliderSize + 'px'; + p.sld.style.height = THIS.height + 'px'; + + // slider gradient + p.sldGrad.draw(THIS.sliderSize, THIS.height, '#000', '#000'); + + // slider border + p.sldB.style.display = displaySlider ? 'block' : 'none'; + p.sldB.style.position = 'absolute'; + p.sldB.style.right = THIS.padding + 'px'; + p.sldB.style.top = THIS.padding + 'px'; + p.sldB.style.border = THIS.insetWidth + 'px solid'; + p.sldB.style.borderColor = THIS.insetColor; + + // slider mouse area + p.sldM._jscInstance = THIS; + p.sldM._jscControlName = 'sld'; + p.sldM.style.display = displaySlider ? 'block' : 'none'; + p.sldM.style.position = 'absolute'; + p.sldM.style.right = '0'; + p.sldM.style.top = '0'; + p.sldM.style.width = (THIS.sliderSize + padToSliderPadding / 2 + THIS.padding + 2 * THIS.insetWidth) + 'px'; + p.sldM.style.height = dims[1] + 'px'; + p.sldM.style.cursor = 'default'; + + // slider pointer inner and outer border + p.sldPtrIB.style.border = + p.sldPtrOB.style.border = + THIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor; + + // slider pointer outer border + p.sldPtrOB.style.position = 'absolute'; + p.sldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px'; + p.sldPtrOB.style.top = '0'; + + // slider pointer middle border + p.sldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor; + + // slider pointer spacer + p.sldPtrS.style.width = THIS.sliderSize + 'px'; + p.sldPtrS.style.height = sliderPtrSpace + 'px'; + + // the Close button + function setBtnBorder () { + var insetColors = THIS.insetColor.split(/\s+/); + var outsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1]; + p.btn.style.borderColor = outsetColor; + } + p.btn.style.display = THIS.closable ? 'block' : 'none'; + p.btn.style.position = 'absolute'; + p.btn.style.left = THIS.padding + 'px'; + p.btn.style.bottom = THIS.padding + 'px'; + p.btn.style.padding = '0 15px'; + p.btn.style.height = THIS.buttonHeight + 'px'; + p.btn.style.border = THIS.insetWidth + 'px solid'; + setBtnBorder(); + p.btn.style.color = THIS.buttonColor; + p.btn.style.font = '12px sans-serif'; + p.btn.style.textAlign = 'center'; + try { + p.btn.style.cursor = 'pointer'; + } catch(eOldIE) { + p.btn.style.cursor = 'hand'; + } + p.btn.onmousedown = function () { + THIS.hide(); + }; + p.btnT.style.lineHeight = THIS.buttonHeight + 'px'; + p.btnT.innerHTML = ''; + p.btnT.appendChild(document.createTextNode(THIS.closeText)); + + // place pointers + redrawPad(); + redrawSld(); + + // If we are changing the owner without first closing the picker, + // make sure to first deal with the old owner + if (jsc.picker.owner && jsc.picker.owner !== THIS) { + jsc.unsetClass(jsc.picker.owner.targetElement, THIS.activeClass); + } + + // Set the new picker owner + jsc.picker.owner = THIS; + + // The redrawPosition() method needs picker.owner to be set, that's why we call it here, + // after setting the owner + if (jsc.isElementType(container, 'body')) { + jsc.redrawPosition(); + } else { + jsc._drawPosition(THIS, 0, 0, 'relative', false); + } + + if (p.wrap.parentNode != container) { + container.appendChild(p.wrap); + } + + jsc.setClass(THIS.targetElement, THIS.activeClass); + } + + + function redrawPad () { + // redraw the pad pointer + switch (jsc.getPadYComponent(THIS)) { + case 's': var yComponent = 1; break; + case 'v': var yComponent = 2; break; + } + var x = Math.round((THIS.hsv[0] / 360) * (THIS.width - 1)); + var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1)); + var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize); + var ofs = -Math.floor(crossOuterSize / 2); + jsc.picker.cross.style.left = (x + ofs) + 'px'; + jsc.picker.cross.style.top = (y + ofs) + 'px'; + + // redraw the slider + switch (jsc.getSliderComponent(THIS)) { + case 's': + var rgb1 = HSV_RGB(THIS.hsv[0], 100, THIS.hsv[2]); + var rgb2 = HSV_RGB(THIS.hsv[0], 0, THIS.hsv[2]); + var color1 = 'rgb(' + + Math.round(rgb1[0]) + ',' + + Math.round(rgb1[1]) + ',' + + Math.round(rgb1[2]) + ')'; + var color2 = 'rgb(' + + Math.round(rgb2[0]) + ',' + + Math.round(rgb2[1]) + ',' + + Math.round(rgb2[2]) + ')'; + jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2); + break; + case 'v': + var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 100); + var color1 = 'rgb(' + + Math.round(rgb[0]) + ',' + + Math.round(rgb[1]) + ',' + + Math.round(rgb[2]) + ')'; + var color2 = '#000'; + jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2); + break; + } + } + + + function redrawSld () { + var sldComponent = jsc.getSliderComponent(THIS); + if (sldComponent) { + // redraw the slider pointer + switch (sldComponent) { + case 's': var yComponent = 1; break; + case 'v': var yComponent = 2; break; + } + var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1)); + jsc.picker.sldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(sliderPtrSpace / 2)) + 'px'; + } + } + + + function isPickerOwner () { + return jsc.picker && jsc.picker.owner === THIS; + } + + + function blurValue () { + THIS.importColor(); + } + + + // Find the target element + if (typeof targetElement === 'string') { + var id = targetElement; + var elm = document.getElementById(id); + if (elm) { + this.targetElement = elm; + } else { + jsc.warn('Could not find target element with ID \'' + id + '\''); + } + } else if (targetElement) { + this.targetElement = targetElement; + } else { + jsc.warn('Invalid target element: \'' + targetElement + '\''); + } + + if (this.targetElement._jscLinkedInstance) { + jsc.warn('Cannot link jscolor twice to the same element. Skipping.'); + return; + } + this.targetElement._jscLinkedInstance = this; + + // Find the value element + this.valueElement = jsc.fetchElement(this.valueElement); + // Find the style element + this.styleElement = jsc.fetchElement(this.styleElement); + + var THIS = this; + var container = + this.container ? + jsc.fetchElement(this.container) : + document.getElementsByTagName('body')[0]; + var sliderPtrSpace = 3; // px + + // For BUTTON elements it's important to stop them from sending the form when clicked + // (e.g. in Safari) + if (jsc.isElementType(this.targetElement, 'button')) { + if (this.targetElement.onclick) { + var origCallback = this.targetElement.onclick; + this.targetElement.onclick = function (evt) { + origCallback.call(this, evt); + return false; + }; + } else { + this.targetElement.onclick = function () { return false; }; + } + } + + /* + var elm = this.targetElement; + do { + // If the target element or one of its offsetParents has fixed position, + // then use fixed positioning instead + // + // Note: In Firefox, getComputedStyle returns null in a hidden iframe, + // that's why we need to check if the returned style object is non-empty + var currStyle = jsc.getStyle(elm); + if (currStyle && currStyle.position.toLowerCase() === 'fixed') { + this.fixed = true; + } + + if (elm !== this.targetElement) { + // attach onParentScroll so that we can recompute the picker position + // when one of the offsetParents is scrolled + if (!elm._jscEventsAttached) { + jsc.attachEvent(elm, 'scroll', jsc.onParentScroll); + elm._jscEventsAttached = true; + } + } + } while ((elm = elm.offsetParent) && !jsc.isElementType(elm, 'body')); + */ + + // valueElement + if (this.valueElement) { + if (jsc.isElementType(this.valueElement, 'input')) { + var updateField = function () { + THIS.fromString(THIS.valueElement.value, jsc.leaveValue); + jsc.dispatchFineChange(THIS); + }; + jsc.attachEvent(this.valueElement, 'keyup', updateField); + jsc.attachEvent(this.valueElement, 'input', updateField); + jsc.attachEvent(this.valueElement, 'blur', blurValue); + this.valueElement.setAttribute('autocomplete', 'off'); + } + } + + // styleElement + if (this.styleElement) { + this.styleElement._jscOrigStyle = { + backgroundImage : this.styleElement.style.backgroundImage, + backgroundColor : this.styleElement.style.backgroundColor, + color : this.styleElement.style.color + }; + } + + if (this.value) { + // Try to set the color from the .value option and if unsuccessful, + // export the current color + this.fromString(this.value) || this.exportColor(); + } else { + this.importColor(); + } + } + +}; + + +//================================ +// Public properties and methods +//================================ + + +// By default, search for all elements with class="jscolor" and install a color picker on them. +// +// You can change what class name will be looked for by setting the property jscolor.lookupClass +// anywhere in your HTML document. To completely disable the automatic lookup, set it to null. +// +jsc.jscolor.lookupClass = 'jscolor'; + + +jsc.jscolor.installByClassName = function (className) { + var inputElms = document.getElementsByTagName('input'); + var buttonElms = document.getElementsByTagName('button'); + + jsc.tryInstallOnElements(inputElms, className); + jsc.tryInstallOnElements(buttonElms, className); +}; + + +jsc.register(); + + +return jsc.jscolor; + + +})(); } diff --git a/apps/theming/js/3rdparty/jscolor/jscolor.min.js b/apps/theming/js/3rdparty/jscolor/jscolor.min.js new file mode 100644 index 0000000000000..2a7a788bed2fd --- /dev/null +++ b/apps/theming/js/3rdparty/jscolor/jscolor.min.js @@ -0,0 +1,10 @@ +/** + * jscolor - JavaScript Color Picker + * + * @link http://jscolor.com + * @license For open source use: GPLv3 + * For commercial use: JSColor Commercial License + * @author Jan Odvarko + * + * See usage examples at http://jscolor.com/examples/ + */"use strict";window.jscolor||(window.jscolor=function(){var e={register:function(){e.attachDOMReadyEvent(e.init),e.attachEvent(document,"mousedown",e.onDocumentMouseDown),e.attachEvent(document,"touchstart",e.onDocumentTouchStart),e.attachEvent(window,"resize",e.onWindowResize)},init:function(){e.jscolor.lookupClass&&e.jscolor.installByClassName(e.jscolor.lookupClass)},tryInstallOnElements:function(t,n){var r=new RegExp("(^|\\s)("+n+")(\\s*(\\{[^}]*\\})|\\s|$)","i");for(var i=0;is[u]?-r[u]+n[u]+i[u]/2>s[u]/2&&n[u]+i[u]-o[u]>=0?n[u]+i[u]-o[u]:n[u]:n[u],-r[a]+n[a]+i[a]+o[a]-l+l*f>s[a]?-r[a]+n[a]+i[a]/2>s[a]/2&&n[a]+i[a]-l-l*f>=0?n[a]+i[a]-l-l*f:n[a]+i[a]-l+l*f:n[a]+i[a]-l+l*f>=0?n[a]+i[a]-l+l*f:n[a]+i[a]-l-l*f];var h=c[u],p=c[a],d=t.fixed?"fixed":"absolute",v=(c[0]+o[0]>n[0]||c[0]2)switch(e.mode.charAt(2).toLowerCase()){case"s":return"s";case"v":return"v"}return null},onDocumentMouseDown:function(t){t||(t=window.event);var n=t.target||t.srcElement;n._jscLinkedInstance?n._jscLinkedInstance.showOnClick&&n._jscLinkedInstance.show():n._jscControlName?e.onControlPointerStart(t,n,n._jscControlName,"mouse"):e.picker&&e.picker.owner&&e.picker.owner.hide()},onDocumentTouchStart:function(t){t||(t=window.event);var n=t.target||t.srcElement;n._jscLinkedInstance?n._jscLinkedInstance.showOnClick&&n._jscLinkedInstance.show():n._jscControlName?e.onControlPointerStart(t,n,n._jscControlName,"touch"):e.picker&&e.picker.owner&&e.picker.owner.hide()},onWindowResize:function(t){e.redrawPosition()},onParentScroll:function(t){e.picker&&e.picker.owner&&e.picker.owner.hide()},_pointerMoveEvent:{mouse:"mousemove",touch:"touchmove"},_pointerEndEvent:{mouse:"mouseup",touch:"touchend"},_pointerOrigin:null,_capturedTarget:null,onControlPointerStart:function(t,n,r,i){var s=n._jscInstance;e.preventDefault(t),e.captureTarget(n);var o=function(s,o){e.attachGroupEvent("drag",s,e._pointerMoveEvent[i],e.onDocumentPointerMove(t,n,r,i,o)),e.attachGroupEvent("drag",s,e._pointerEndEvent[i],e.onDocumentPointerEnd(t,n,r,i))};o(document,[0,0]);if(window.parent&&window.frameElement){var u=window.frameElement.getBoundingClientRect(),a=[-u.left,-u.top];o(window.parent.window.document,a)}var f=e.getAbsPointerPos(t),l=e.getRelPointerPos(t);e._pointerOrigin={x:f.x-l.x,y:f.y-l.y};switch(r){case"pad":switch(e.getSliderComponent(s)){case"s":s.hsv[1]===0&&s.fromHSV(null,100,null);break;case"v":s.hsv[2]===0&&s.fromHSV(null,null,100)}e.setPad(s,t,0,0);break;case"sld":e.setSld(s,t,0)}e.dispatchFineChange(s)},onDocumentPointerMove:function(t,n,r,i,s){return function(t){var i=n._jscInstance;switch(r){case"pad":t||(t=window.event),e.setPad(i,t,s[0],s[1]),e.dispatchFineChange(i);break;case"sld":t||(t=window.event),e.setSld(i,t,s[1]),e.dispatchFineChange(i)}}},onDocumentPointerEnd:function(t,n,r,i){return function(t){var r=n._jscInstance;e.detachGroupEvents("drag"),e.releaseTarget(),e.dispatchChange(r)}},dispatchChange:function(t){t.valueElement&&e.isElementType(t.valueElement,"input")&&e.fireEvent(t.valueElement,"change")},dispatchFineChange:function(e){if(e.onFineChange){var t;typeof e.onFineChange=="string"?t=new Function(e.onFineChange):t=e.onFineChange,t.call(e)}},setPad:function(t,n,r,i){var s=e.getAbsPointerPos(n),o=r+s.x-e._pointerOrigin.x-t.padding-t.insetWidth,u=i+s.y-e._pointerOrigin.y-t.padding-t.insetWidth,a=o*(360/(t.width-1)),f=100-u*(100/(t.height-1));switch(e.getPadYComponent(t)){case"s":t.fromHSV(a,f,null,e.leaveSld);break;case"v":t.fromHSV(a,null,f,e.leaveSld)}},setSld:function(t,n,r){var i=e.getAbsPointerPos(n),s=r+i.y-e._pointerOrigin.y-t.padding-t.insetWidth,o=100-s*(100/(t.height-1));switch(e.getSliderComponent(t)){case"s":t.fromHSV(null,o,null,e.leavePad);break;case"v":t.fromHSV(null,null,o,e.leavePad)}},_vmlNS:"jsc_vml_",_vmlCSS:"jsc_vml_css_",_vmlReady:!1,initVML:function(){if(!e._vmlReady){var t=document;t.namespaces[e._vmlNS]||t.namespaces.add(e._vmlNS,"urn:schemas-microsoft-com:vml");if(!t.styleSheets[e._vmlCSS]){var n=["shape","shapetype","group","background","path","formulas","handles","fill","stroke","shadow","textbox","textpath","imagedata","line","polyline","curve","rect","roundrect","oval","arc","image"],r=t.createStyleSheet();r.owningElement.id=e._vmlCSS;for(var i=0;i=3&&(s=r[0].match(i))&&(o=r[1].match(i))&&(u=r[2].match(i))){var a=parseFloat((s[1]||"0")+(s[2]||"")),f=parseFloat((o[1]||"0")+(o[2]||"")),l=parseFloat((u[1]||"0")+(u[2]||""));return this.fromRGB(a,f,l,t),!0}}return!1},this.toString=function(){return(256|Math.round(this.rgb[0])).toString(16).substr(1)+(256|Math.round(this.rgb[1])).toString(16).substr(1)+(256|Math.round(this.rgb[2])).toString(16).substr(1)},this.toHEXString=function(){return"#"+this.toString().toUpperCase()},this.toRGBString=function(){return"rgb("+Math.round(this.rgb[0])+","+Math.round(this.rgb[1])+","+Math.round(this.rgb[2])+")"},this.isLight=function(){return.213*this.rgb[0]+.715*this.rgb[1]+.072*this.rgb[2]>127.5},this._processParentElementsInDOM=function(){if(this._linkedElementsProcessed)return;this._linkedElementsProcessed=!0;var t=this.targetElement;do{var n=e.getStyle(t);n&&n.position.toLowerCase()==="fixed"&&(this.fixed=!0),t!==this.targetElement&&(t._jscEventsAttached||(e.attachEvent(t,"scroll",e.onParentScroll),t._jscEventsAttached=!0))}while((t=t.parentNode)&&!e.isElementType(t,"body"))};if(typeof t=="string"){var h=t,p=document.getElementById(h);p?this.targetElement=p:e.warn("Could not find target element with ID '"+h+"'")}else t?this.targetElement=t:e.warn("Invalid target element: '"+t+"'");if(this.targetElement._jscLinkedInstance){e.warn("Cannot link jscolor twice to the same element. Skipping.");return}this.targetElement._jscLinkedInstance=this,this.valueElement=e.fetchElement(this.valueElement),this.styleElement=e.fetchElement(this.styleElement);var d=this,v=this.container?e.fetchElement(this.container):document.getElementsByTagName("body")[0],m=3;if(e.isElementType(this.targetElement,"button"))if(this.targetElement.onclick){var g=this.targetElement.onclick;this.targetElement.onclick=function(e){return g.call(this,e),!1}}else this.targetElement.onclick=function(){return!1};if(this.valueElement&&e.isElementType(this.valueElement,"input")){var y=function(){d.fromString(d.valueElement.value,e.leaveValue),e.dispatchFineChange(d)};e.attachEvent(this.valueElement,"keyup",y),e.attachEvent(this.valueElement,"input",y),e.attachEvent(this.valueElement,"blur",c),this.valueElement.setAttribute("autocomplete","off")}this.styleElement&&(this.styleElement._jscOrigStyle={backgroundImage:this.styleElement.style.backgroundImage,backgroundColor:this.styleElement.style.backgroundColor,color:this.styleElement.style.color}),this.value?this.fromString(this.value)||this.exportColor():this.importColor()}};return e.jscolor.lookupClass="jscolor",e.jscolor.installByClassName=function(t){var n=document.getElementsByTagName("input"),r=document.getElementsByTagName("button");e.tryInstallOnElements(n,t),e.tryInstallOnElements(r,t)},e.register(),e.jscolor}()); \ No newline at end of file diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 317773a32c2c4..7645654307675 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -18,3 +18,86 @@ * along with this program. If not, see * */ + +function setThemingValue(setting, value) { + $.post( + OC.generateUrl('/apps/theming/ajax/updateStylesheet'), {'setting' : setting, 'value' : value} + ); + preview(setting, value); +} + +function preview(setting, value) { + if (setting === 'color') { + var headerClass = document.getElementById('header'); + headerClass.style.background = value; + headerClass.style.backgroundImage = '../img/logo-icon.svg'; + + } + if (setting === 'logoName') { + var logos = document.getElementsByClassName('logo-icon'); + for (var i = 0; i < logos.length; i++) { + logos[i].style.background= "url('" + OC.getRootPath() + "/themes/theming-app/core/img/" + value + "')"; + } + } +} + +$(document).ready(function () { + + var uploadparms = { + pasteZone: null, + done: function (e, data) { + preview('logoName', data.result.name); + }, + submit: function(e, data) { + }, + fail: function (e, data){ + } + }; + + $('#uploadlogo').fileupload(uploadparms); + + $('#theming-name').keyup(function (e) { + if (e.keyCode == 13) { + setThemingValue('name', $(this).val()); + } + }).focusout(function (e) { + setThemingValue('name', $(this).val()); + }); + + $('#theming-url').keyup(function (e) { + if (e.keyCode == 13) { + setThemingValue('url', $(this).val()); + } + }).focusout(function (e) { + setThemingValue('url', $(this).val()); + }); + + $('#theming-slogan').keyup(function (e) { + if (e.keyCode == 13) { + setThemingValue('slogan', $(this).val()); + } + }).focusout(function (e) { + setThemingValue('slogan', $(this).val()); + }); + + $('#theming-color').change(function (e) { + setThemingValue('color', '#' + $(this).val()); + }); + + $('.theme-undo').click(function (e) { + var setting = $(this).data('setting'); + $.post( + OC.generateUrl('/apps/theming/ajax/undoChanges'), {'setting' : setting} + ).done(function(data) { + if (setting === 'color') { + var colorPicker = document.getElementById('theming-color'); + colorPicker.style.backgroundColor = data.value; + colorPicker.value = data.value.slice(1); + } else if (setting !== 'logoName') { + var input = document.getElementById('theming-'+setting); + input.value = data.value; + } + preview(setting, data.value); + }); + }); +}); diff --git a/apps/theming/lib/controller/themingcontroller.php b/apps/theming/lib/controller/themingcontroller.php new file mode 100644 index 0000000000000..0aa95384a812a --- /dev/null +++ b/apps/theming/lib/controller/themingcontroller.php @@ -0,0 +1,86 @@ + + * + * @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 . + * + */ + + +namespace OCA\Theming\Controller; + + +use OCA\Theming\Template; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\DataResponse; +use OCP\IRequest; + +/** + * Class ThemingController + * + * handle ajax requests to update the theme + * + * @package OCA\Theming\Controller + */ +class ThemingController extends Controller { + + /** @var Template */ + private $template; + + public function __construct($appName, IRequest $request, Template $template) { + parent::__construct($appName, $request); + + $this->template = $template; + } + + /** + * @param $setting + * @param $value + * @return DataResponse + * @internal param string $color + */ + public function updateStylesheet($setting, $value) { + $this->template->set($setting, $value); + return new DataResponse(); + } + + /** + * update Nextcloud logo + * + * @return DataResponse + */ + public function updateLogo() { + $newLogo = $this->request->getUploadedFile('uploadlogo'); + if (empty($newLogo)) { + return new DataResponse(['message' => 'No logo uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY); + } + $this->template->set('logoName', $newLogo['name']); + rename($newLogo['tmp_name'], \OC::$SERVERROOT . '/themes/theming-app/core/img/' . $newLogo['name']); + + return new DataResponse(['name' => $newLogo['name']]); + } + + /** + * revert setting to default value + * + * @param string $setting setting which should be reverted + * @return DataResponse + */ + public function undo($setting) { + $value = $this->template->undo($setting); + return new DataResponse(['value' => $value]); + } +} diff --git a/apps/theming/lib/init.php b/apps/theming/lib/init.php new file mode 100644 index 0000000000000..287aa589caca7 --- /dev/null +++ b/apps/theming/lib/init.php @@ -0,0 +1,94 @@ + + * + * @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 . + * + */ + + +namespace OCA\Theming; + + +use OCP\App\ManagerEvent; +use OCP\IConfig; +use OCP\ILogger; + +/** + * Class Init + * + * Initialize the app and make sure that all directories and files exists + * + * @package OCA\Theming + */ +class Init { + + /** @var IConfig */ + private $config; + + /** @var ILogger */ + private $logger; + + /** + * Init constructor. + * + * @param IConfig $config + * @param ILogger $logger + */ + public function __construct(IConfig $config, ILogger $logger) { + $this->config = $config; + $this->logger = $logger; + } + + /** + * prepare folders with the theming app and add the default values to it + */ + public function prepareThemeFolder() { + + if ($this->config->getSystemValue('theme', 'default') === 'theming-app') { + return; + } + + if (!is_writable(\OC::$SERVERROOT . '/themes')) { + $this->logger->warning('Themes folder is read only, can not prepare the theming-app folder', + ['app' => 'theming'] + ); + } + + $this->config->setSystemValue('theme', 'theming-app'); + + if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app')) { + mkdir(\OC::$SERVERROOT . '/themes/theming-app'); + } + + if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core')) { + mkdir(\OC::$SERVERROOT . '/themes/theming-app/core'); + } + + if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core/img')) { + mkdir(\OC::$SERVERROOT . '/themes/theming-app/core/img'); + } + + if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core/css')) { + mkdir(\OC::$SERVERROOT . '/themes/theming-app/core/css'); + } + + if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core/img/logo-icon.svg')) { + copy(\OC::$SERVERROOT . '/core/img/logo-icon.svg' ,\OC::$SERVERROOT . '/themes/theming-app/core/img/logo-icon.svg'); + } + } + +} diff --git a/apps/theming/lib/template.php b/apps/theming/lib/template.php new file mode 100644 index 0000000000000..177ead698898f --- /dev/null +++ b/apps/theming/lib/template.php @@ -0,0 +1,172 @@ + + * + * @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 . + * + */ + + +namespace OCA\Theming; + + +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; + +/** + * Class Template + * + * Handle all the values which can be modified by this app + * + * @package OCA\Theming + */ +class Template { + + /** @var IConfig */ + private $config; + + /** @var IL10N */ + private $l; + + /** @var IURLGenerator */ + private $urlGenerator; + + /** @var Init */ + private $init; + + /** @var string */ + private $name; + + /** @var string */ + private $url; + + /** @var string */ + private $slogan; + + /** @var string */ + private $color; + + /** @var string */ + private $logoName; + + /** + * Template constructor. + * + * @param IConfig $config + * @param IL10N $l + * @param IURLGenerator $urlGenerator + * @param Init $init + */ + public function __construct(IConfig $config, + IL10N $l, + IURLGenerator $urlGenerator, + Init $init + ) { + $this->config = $config; + $this->l = $l; + $this->urlGenerator = $urlGenerator; + $this->init = $init; + + $this->name = 'Nextcloud'; + $this->url = 'https://nextcloud.com'; + $this->slogan = $this->l->t('a safe home for all your data'); + $this->color = '#0082c9'; + $this->logoName = 'logo-icon.svg'; + } + + public function getName() { + return $this->config->getAppValue('theming', 'name', $this->name); + } + + public function getUrl() { + return $this->config->getAppValue('theming', 'url', $this->url); + } + + public function getSlogan() { + return $this->config->getAppValue('theming', 'slogan', $this->slogan); + } + + public function getColor() { + return $this->config->getAppValue('theming', 'color', $this->color); + } + + public function getLogoName() { + return $this->config->getAppValue('theming', 'logoName', $this->logoName); + } + + /** + * update setting in the database + * + * @param $setting + * @param $value + */ + public function set($setting, $value) { + $this->init->prepareThemeFolder(); + $this->config->setAppValue('theming', $setting, $value); + $this->writeCSSFile(); + } + + /** + * revert settings to the default value + * + * @param string $setting setting which should be reverted + * @return string default value + */ + public function undo($setting) { + $returnValue = ''; + if ($this->$setting) { + $this->config->setAppValue('theming', $setting, $this->$setting); + $this->writeCSSFile(); + $returnValue = $this->$setting; + } + + return $returnValue; + } + + /** + * write setting to a css file + */ + private function writeCSSFile() { + $logo = $this->getLogoName(); + $color = $this->getColor(); + + $css = " + #body-user #header, + #body-settings #header, + #body-public #header { + background-color: $color; + } + + + /* use logos from theme */ + #header .logo { + background-image: url('../img/$logo'); + width: 250px; + height: 121px; + } + #header .logo-icon { + background-image: url('../img/$logo'); + width: 62px; + height: 34px; + }"; + + $root = \OC::$SERVERROOT . '/themes/theming-app/core'; + + file_put_contents($root . '/css/styles.css', $css); + } + +} diff --git a/apps/theming/settings/settings-admin.php b/apps/theming/settings/settings-admin.php index 8c7effb31071f..c79eb1475fb54 100644 --- a/apps/theming/settings/settings-admin.php +++ b/apps/theming/settings/settings-admin.php @@ -22,6 +22,39 @@ \OC_Util::checkAdminUser(); +$config = \OC::$server->getConfig(); +$l = \OC::$server->getL10N('theming'); +$urlGenerator = \OC::$server->getURLGenerator(); +$init = new \OCA\Theming\Init($config, \OC::$server->getLogger()); + +$theming = new \OCA\Theming\Template( + $config, + $l, + \OC::$server->getURLGenerator(), + $init +); + +$themable = true; +$errorMessage = ''; +$theme = $config->getSystemValue('theme', 'default'); + +if ($theme !== 'theming-app' && $theme !== 'default') { + $themable = false; + $errorMessage = $l->t('You already use a custom theme'); +} elseif (!is_writable(\OC::$SERVERROOT . '/themes')) { + $themable = false; + $errorMessage = $l->t('Themes folder is read-only, please update the permissions to read-write'); +} + $template = new OCP\Template('theming', 'settings-admin'); +$template->assign('themable', $themable); +$template->assign('errorMessage', $errorMessage); +$template->assign('name', $theming->getName()); +$template->assign('url', $theming->getUrl()); +$template->assign('slogan', $theming->getSlogan()); +$template->assign('color', $theming->getColor()); +$path = $urlGenerator->linkToRoute('theming.Theming.updateLogo'); +$template->assign('uploadLogoRoute', $path); + return $template->fetchPage(); diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index 82d21751abc4e..cfc18de9c133a 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -2,24 +2,39 @@ /** @var array $_ */ /** @var OC_L10N $l */ script('theming', 'settings-admin'); -style('theming', 'settings-admin') +script('theming', '3rdparty/jscolor/jscolor'); +style('theming', 'settings-admin'); ?>

t('Theming')); ?>

- +

- +

+

- + Name: +

- + URL: +

- + Slogan: +

- + Color: +

+

+

+ Logo: + + + +
+

+
diff --git a/lib/private/legacy/defaults.php b/lib/private/legacy/defaults.php index 2a97cfe89edde..f0cc4c91851ad 100644 --- a/lib/private/legacy/defaults.php +++ b/lib/private/legacy/defaults.php @@ -31,8 +31,13 @@ class OC_Defaults { private $theme; + + /** @var \OCP\IL10N */ private $l; + /** @var \OCA\Theming\Template */ + private $template; + private $defaultEntity; private $defaultName; private $defaultTitle; @@ -49,21 +54,45 @@ class OC_Defaults { function __construct() { $this->l = \OC::$server->getL10N('lib'); + $config = \OC::$server->getConfig(); + + + try { + $themingAppEnabled = $config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming'); + } catch (\Exception $e) { + $themingAppEnabled = false; + } + + $config = \OC::$server->getConfig(); + + if ($themingAppEnabled) { + $this->template = new \OCA\Theming\Template( + $config, + $this->l, + \OC::$server->getURLGenerator(), + new \OCA\Theming\Init($config, \OC::$server->getLogger()) + ); + $this->defaultName = $this->template->getName(); /* short name, used when referring to the software */ + $this->defaultBaseUrl = $this->template->getUrl(); + $this->defaultSlogan = $this->template->getSlogan(); + $this->defaultMailHeaderColor = $this->template->getColor(); /* header color of mail notifications */ + } else { + $this->defaultName = 'Nextcloud'; + $this->defaultBaseUrl = 'https://nextcloud.com'; + $this->defaultSlogan = $this->l->t('a safe home for all your data'); + $this->defaultMailHeaderColor = '#0082c9'; /* header color of mail notifications */ + } $version = \OCP\Util::getVersion(); $this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */ - $this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */ $this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */ - $this->defaultBaseUrl = 'https://nextcloud.com'; $this->defaultSyncClientUrl = 'https://nextcloud.com/install'; $this->defaultiOSClientUrl = 'https://itunes.apple.com/us/app/owncloud/id543672169?mt=8'; $this->defaultiTunesAppId = '543672169'; $this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.owncloud.android'; $this->defaultDocBaseUrl = 'https://doc.owncloud.org'; $this->defaultDocVersion = $version[0] . '.' . $version[1]; // used to generate doc links - $this->defaultSlogan = $this->l->t('a safe home for all your data'); $this->defaultLogoClaim = ''; - $this->defaultMailHeaderColor = '#0082c9'; /* header color of mail notifications */ $themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php'; if (file_exists($themePath)) { From dfe2273cca2cf1ee4e73aedecedbb8055709b0ee Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 16 Jun 2016 17:30:18 +0200 Subject: [PATCH 16/81] add some visual feedback if the operation was succesful or not --- apps/theming/css/settings-admin.css | 4 ++ apps/theming/js/settings-admin.js | 28 ++++++--- .../lib/controller/themingcontroller.php | 63 +++++++++++++++++-- apps/theming/templates/settings-admin.php | 3 +- 4 files changed, 82 insertions(+), 16 deletions(-) diff --git a/apps/theming/css/settings-admin.css b/apps/theming/css/settings-admin.css index b0739465ef246..931e4d4508b41 100644 --- a/apps/theming/css/settings-admin.css +++ b/apps/theming/css/settings-admin.css @@ -22,3 +22,7 @@ #theming .icon-upload { display: inline-flex; } + +div#theming_settings_msg { + margin-left: 10px; +} diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 7645654307675..dd2f051163c37 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -20,9 +20,14 @@ */ function setThemingValue(setting, value) { + OC.msg.startSaving('#theming_settings_msg'); $.post( OC.generateUrl('/apps/theming/ajax/updateStylesheet'), {'setting' : setting, 'value' : value} - ); + ).done(function(response) { + OC.msg.finishedSaving('#theming_settings_msg', response); + }).fail(function(response) { + OC.msg.finishedSaving('#theming_settings_msg', response); + }); preview(setting, value); } @@ -45,12 +50,15 @@ $(document).ready(function () { var uploadparms = { pasteZone: null, - done: function (e, data) { - preview('logoName', data.result.name); + done: function (e, response) { + preview('logoName', response.result.data.name); + OC.msg.finishedSaving('#theming_settings_msg', response.result); }, - submit: function(e, data) { + submit: function(e, response) { + OC.msg.startSaving('#theming_settings_msg'); }, fail: function (e, data){ + OC.msg.finishedSaving('#theming_settings_msg', response); } }; @@ -86,18 +94,20 @@ $(document).ready(function () { $('.theme-undo').click(function (e) { var setting = $(this).data('setting'); + OC.msg.startSaving('#theming_settings_msg'); $.post( OC.generateUrl('/apps/theming/ajax/undoChanges'), {'setting' : setting} - ).done(function(data) { + ).done(function(response) { if (setting === 'color') { var colorPicker = document.getElementById('theming-color'); - colorPicker.style.backgroundColor = data.value; - colorPicker.value = data.value.slice(1); + colorPicker.style.backgroundColor = response.data.value; + colorPicker.value = response.data.value.slice(1); } else if (setting !== 'logoName') { var input = document.getElementById('theming-'+setting); - input.value = data.value; + input.value = response.data.value; } - preview(setting, data.value); + preview(setting, response.data.value); + OC.msg.finishedSaving('#theming_settings_msg', response); }); }); }); diff --git a/apps/theming/lib/controller/themingcontroller.php b/apps/theming/lib/controller/themingcontroller.php index 0aa95384a812a..5ffbbf7176997 100644 --- a/apps/theming/lib/controller/themingcontroller.php +++ b/apps/theming/lib/controller/themingcontroller.php @@ -25,7 +25,9 @@ use OCA\Theming\Template; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\IL10N; use OCP\IRequest; /** @@ -39,11 +41,28 @@ class ThemingController extends Controller { /** @var Template */ private $template; - - public function __construct($appName, IRequest $request, Template $template) { + + /** @var IL10N */ + private $l; + + /** + * ThemingController constructor. + * + * @param string $appName + * @param IRequest $request + * @param Template $template + * @param IL10N $l + */ + public function __construct( + $appName, + IRequest $request, + Template $template, + IL10N $l + ) { parent::__construct($appName, $request); $this->template = $template; + $this->l = $l; } /** @@ -54,7 +73,15 @@ public function __construct($appName, IRequest $request, Template $template) { */ public function updateStylesheet($setting, $value) { $this->template->set($setting, $value); - return new DataResponse(); + return new DataResponse( + [ + 'data' => + [ + 'message' => $this->l->t('Saved') + ], + 'status' => 'success' + ] + ); } /** @@ -65,12 +92,27 @@ public function updateStylesheet($setting, $value) { public function updateLogo() { $newLogo = $this->request->getUploadedFile('uploadlogo'); if (empty($newLogo)) { - return new DataResponse(['message' => 'No logo uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY); + return new DataResponse( + [ + 'data' => [ + 'message' => $this->l->t('No logo uploaded') + ] + ], + Http::STATUS_UNPROCESSABLE_ENTITY); } $this->template->set('logoName', $newLogo['name']); rename($newLogo['tmp_name'], \OC::$SERVERROOT . '/themes/theming-app/core/img/' . $newLogo['name']); - return new DataResponse(['name' => $newLogo['name']]); + return new DataResponse( + [ + 'data' => + [ + 'name' => $newLogo['name'], + 'message' => $this->l->t('Saved') + ], + 'status' => 'success' + ] + ); } /** @@ -81,6 +123,15 @@ public function updateLogo() { */ public function undo($setting) { $value = $this->template->undo($setting); - return new DataResponse(['value' => $value]); + return new DataResponse( + [ + 'data' => + [ + 'value' => $value, + 'message' => $this->l->t('Saved') + ], + 'status' => 'success' + ] + ); } } diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index cfc18de9c133a..4e2277b0533e2 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -6,7 +6,8 @@ style('theming', 'settings-admin'); ?>
-

t('Theming')); ?>

+

t('Theming')); ?>

+

From 92e2d1c972f3d0d76d93216a9b2336300a836c94 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 21 Jun 2016 21:21:46 +0200 Subject: [PATCH 17/81] Migrate logic to dynamic controller Also adds support for having custom login backgrounds --- apps/theming/appinfo/app.php | 31 +- apps/theming/appinfo/info.xml | 2 +- apps/theming/appinfo/routes.php | 17 +- apps/theming/js/settings-admin.js | 32 +- .../lib/controller/themingcontroller.php | 124 +++++- apps/theming/lib/init.php | 94 ---- apps/theming/lib/template.php | 117 ++--- apps/theming/settings/settings-admin.php | 32 +- apps/theming/templates/settings-admin.php | 24 +- apps/theming/tests/lib/TemplateTest.php | 301 +++++++++++++ .../lib/controller/ThemingControllerTest.php | 405 ++++++++++++++++++ core/js/config.php | 2 +- core/shipped.json | 1 + lib/private/Server.php | 20 + lib/private/legacy/defaults.php | 37 +- lib/private/legacy/template.php | 2 +- 16 files changed, 982 insertions(+), 259 deletions(-) delete mode 100644 apps/theming/lib/init.php create mode 100644 apps/theming/tests/lib/TemplateTest.php create mode 100644 apps/theming/tests/lib/controller/ThemingControllerTest.php diff --git a/apps/theming/appinfo/app.php b/apps/theming/appinfo/app.php index ed7ea3e20f8d6..edf2c7d345ac1 100644 --- a/apps/theming/appinfo/app.php +++ b/apps/theming/appinfo/app.php @@ -1,23 +1,38 @@ + * @copyright Copyright (c) 2016 Bjoern Schiessle + * @copyright Copyright (c) 2016 Lukas Reschke * - * @copyright Copyright (c) 2016, Bjoern Schiessle - * @license AGPL-3.0 + * @license GNU AGPL version 3 or any later version * - * This code is free software: you can redistribute it and/or modify + * 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 opinion) any later version. + * 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 + * 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 + * along with this program. If not, see . * */ \OCP\App::registerAdmin('theming', 'settings/settings-admin'); + +$linkToCSS = \OC::$server->getURLGenerator()->linkToRoute( + 'theming.Theming.getStylesheet', + [ + 'v' => \OC::$server->getConfig()->getAppValue('theming', 'cachebuster', '0'), + ] +); +\OC_Util::addHeader( + 'link', + [ + 'rel' => 'stylesheet', + 'href' => $linkToCSS, + ] +); + diff --git a/apps/theming/appinfo/info.xml b/apps/theming/appinfo/info.xml index f0f2fb80afe96..58c839f2758a7 100644 --- a/apps/theming/appinfo/info.xml +++ b/apps/theming/appinfo/info.xml @@ -4,7 +4,7 @@ Theming Adjust the Nextcloud theme AGPL - Bjoern Schiessle + Nextcloud 0.1.0 Theming other diff --git a/apps/theming/appinfo/routes.php b/apps/theming/appinfo/routes.php index 7a2ff1f9dbd4d..dbbae372ffd19 100644 --- a/apps/theming/appinfo/routes.php +++ b/apps/theming/appinfo/routes.php @@ -1,6 +1,7 @@ + * @copyright Copyright (c) 2016 Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -19,7 +20,6 @@ * */ - namespace OCA\Theming\AppInfo; (new \OCP\AppFramework\App('theming'))->registerRoutes($this, array('routes' => array( @@ -38,5 +38,20 @@ 'url' => '/ajax/updateLogo', 'verb' => 'POST' ], + [ + 'name' => 'Theming#getStylesheet', + 'url' => '/styles.css', + 'verb' => 'GET', + ], + [ + 'name' => 'Theming#getLogo', + 'url' => '/logo', + 'verb' => 'GET', + ], + [ + 'name' => 'Theming#getLoginBackground', + 'url' => '/loginbackground', + 'verb' => 'GET', + ], ))); diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index dd2f051163c37..1acd6a97e967d 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -36,22 +36,37 @@ function preview(setting, value) { var headerClass = document.getElementById('header'); headerClass.style.background = value; headerClass.style.backgroundImage = '../img/logo-icon.svg'; - } - if (setting === 'logoName') { + if (setting === 'logoMime') { + console.log(setting); var logos = document.getElementsByClassName('logo-icon'); - for (var i = 0; i < logos.length; i++) { - logos[i].style.background= "url('" + OC.getRootPath() + "/themes/theming-app/core/img/" + value + "')"; + if(value !== '') { + logos[0].style.background = "url('" + OC.generateUrl('/apps/theming/logo') + "')"; + } else { + logos[0].style.background = "url('" + OC.getRootPath() + '/core/img/logo-icon.svg'+"')"; } } } $(document).ready(function () { - var uploadparms = { + var uploadParamsLogo = { + pasteZone: null, + done: function (e, response) { + preview('logoMime', response.result.data.name); + OC.msg.finishedSaving('#theming_settings_msg', response.result); + }, + submit: function(e, response) { + OC.msg.startSaving('#theming_settings_msg'); + }, + fail: function (e, data){ + OC.msg.finishedSaving('#theming_settings_msg', response); + } + }; + var uploadParamsLogin = { pasteZone: null, done: function (e, response) { - preview('logoName', response.result.data.name); + preview('backgroundMime', response.result.data.name); OC.msg.finishedSaving('#theming_settings_msg', response.result); }, submit: function(e, response) { @@ -62,7 +77,8 @@ $(document).ready(function () { } }; - $('#uploadlogo').fileupload(uploadparms); + $('#uploadlogo').fileupload(uploadParamsLogo); + $('#upload-login-background').fileupload(uploadParamsLogin); $('#theming-name').keyup(function (e) { if (e.keyCode == 13) { @@ -102,7 +118,7 @@ $(document).ready(function () { var colorPicker = document.getElementById('theming-color'); colorPicker.style.backgroundColor = response.data.value; colorPicker.value = response.data.value.slice(1); - } else if (setting !== 'logoName') { + } else if (setting !== 'logoMime' && setting !== 'backgroundMime') { var input = document.getElementById('theming-'+setting); input.value = response.data.value; } diff --git a/apps/theming/lib/controller/themingcontroller.php b/apps/theming/lib/controller/themingcontroller.php index 5ffbbf7176997..dd4ff82195160 100644 --- a/apps/theming/lib/controller/themingcontroller.php +++ b/apps/theming/lib/controller/themingcontroller.php @@ -1,6 +1,7 @@ + * @copyright Copyright (c) 2016 Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -19,14 +20,13 @@ * */ - namespace OCA\Theming\Controller; - use OCA\Theming\Template; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; @@ -38,24 +38,26 @@ * @package OCA\Theming\Controller */ class ThemingController extends Controller { - /** @var Template */ private $template; - /** @var IL10N */ private $l; + /** @var IConfig */ + private $config; /** * ThemingController constructor. * * @param string $appName * @param IRequest $request + * @param IConfig $config * @param Template $template * @param IL10N $l */ public function __construct( $appName, IRequest $request, + IConfig $config, Template $template, IL10N $l ) { @@ -63,11 +65,12 @@ public function __construct( $this->template = $template; $this->l = $l; + $this->config = $config; } /** - * @param $setting - * @param $value + * @param string $setting + * @param string $value * @return DataResponse * @internal param string $color */ @@ -85,29 +88,39 @@ public function updateStylesheet($setting, $value) { } /** - * update Nextcloud logo + * Update the logos and background image * * @return DataResponse */ public function updateLogo() { $newLogo = $this->request->getUploadedFile('uploadlogo'); - if (empty($newLogo)) { + $newBackgroundLogo = $this->request->getUploadedFile('upload-login-background'); + if (empty($newLogo) && empty($newBackgroundLogo)) { return new DataResponse( [ 'data' => [ - 'message' => $this->l->t('No logo uploaded') + 'message' => $this->l->t('No file uploaded') ] ], Http::STATUS_UNPROCESSABLE_ENTITY); } - $this->template->set('logoName', $newLogo['name']); - rename($newLogo['tmp_name'], \OC::$SERVERROOT . '/themes/theming-app/core/img/' . $newLogo['name']); - + $name = ''; + if(!empty($newLogo)) { + rename($newLogo['tmp_name'], $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedinstancelogo'); + $this->template->set('logoMime', $newLogo['type']); + $name = $newLogo['name']; + } + if(!empty($newBackgroundLogo)) { + rename($newBackgroundLogo['tmp_name'], $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedbackgroundlogo'); + $this->template->set('backgroundMime', $newBackgroundLogo['type']); + $name = $newBackgroundLogo['name']; + } + return new DataResponse( [ 'data' => [ - 'name' => $newLogo['name'], + 'name' => $name, 'message' => $this->l->t('Saved') ], 'status' => 'success' @@ -116,7 +129,7 @@ public function updateLogo() { } /** - * revert setting to default value + * Revert setting to default value * * @param string $setting setting which should be reverted * @return DataResponse @@ -134,4 +147,87 @@ public function undo($setting) { ] ); } + + /** + * @PublicPage + * @NoCSRFRequired + * + * @return Http\StreamResponse + */ + public function getLogo() { + $pathToLogo = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedinstancelogo'; + if(!file_exists($pathToLogo)) { + return new DataResponse(); + } + + \OC_Response::setExpiresHeader(gmdate('D, d M Y H:i:s', time() + (60*60*24*45)) . ' GMT'); + \OC_Response::enableCaching(); + $response = new Http\StreamResponse($pathToLogo); + $response->cacheFor(3600); + $response->addHeader('Content-Disposition', 'attachment'); + $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'logoMime', '')); + return $response; + } + + /** + * @PublicPage + * @NoCSRFRequired + * + * @return Http\StreamResponse + */ + public function getLoginBackground() { + $pathToLogo = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedbackgroundlogo'; + if(!file_exists($pathToLogo)) { + return new DataResponse(); + } + + \OC_Response::setExpiresHeader(gmdate('D, d M Y H:i:s', time() + (60*60*24*45)) . ' GMT'); + \OC_Response::enableCaching(); + $response = new Http\StreamResponse($pathToLogo); + $response->cacheFor(3600); + $response->addHeader('Content-Disposition', 'attachment'); + $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'backgroundMime', '')); + return $response; + } + + /** + * @NoCSRFRequired + * @PublicPage + * + * @return Http\DataDownloadResponse + */ + public function getStylesheet() { + $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0'); + $responseCss = ''; + $color = $this->config->getAppValue($this->appName, 'color'); + if($color !== '') { + $responseCss .= sprintf( + '#body-user #header,#body-settings #header,#body-public #header {background-color: %s}', + $color + ); + } + $logo = $this->config->getAppValue($this->appName, 'logoMime'); + if($logo !== '') { + $responseCss .= sprintf('#header .logo { + background-image: url(\'./logo?v='.$cacheBusterValue.'\'); + } + #header .logo-icon { + background-image: url(\'./logo?v='.$cacheBusterValue.'\'); + background-size: 62px 34px; + }' + ); + } + $backgroundLogo = $this->config->getAppValue($this->appName, 'backgroundMime'); + if($backgroundLogo !== '') { + $responseCss .= '#body-login { + background-image: url(\'./loginbackground?v='.$cacheBusterValue.'\'); + }'; + } + + \OC_Response::setExpiresHeader(gmdate('D, d M Y H:i:s', time() + (60*60*24*45)) . ' GMT'); + \OC_Response::enableCaching(); + $response = new Http\DataDownloadResponse($responseCss, 'style.css', 'text/css'); + $response->cacheFor(3600); + return $response; + } } diff --git a/apps/theming/lib/init.php b/apps/theming/lib/init.php deleted file mode 100644 index 287aa589caca7..0000000000000 --- a/apps/theming/lib/init.php +++ /dev/null @@ -1,94 +0,0 @@ - - * - * @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 . - * - */ - - -namespace OCA\Theming; - - -use OCP\App\ManagerEvent; -use OCP\IConfig; -use OCP\ILogger; - -/** - * Class Init - * - * Initialize the app and make sure that all directories and files exists - * - * @package OCA\Theming - */ -class Init { - - /** @var IConfig */ - private $config; - - /** @var ILogger */ - private $logger; - - /** - * Init constructor. - * - * @param IConfig $config - * @param ILogger $logger - */ - public function __construct(IConfig $config, ILogger $logger) { - $this->config = $config; - $this->logger = $logger; - } - - /** - * prepare folders with the theming app and add the default values to it - */ - public function prepareThemeFolder() { - - if ($this->config->getSystemValue('theme', 'default') === 'theming-app') { - return; - } - - if (!is_writable(\OC::$SERVERROOT . '/themes')) { - $this->logger->warning('Themes folder is read only, can not prepare the theming-app folder', - ['app' => 'theming'] - ); - } - - $this->config->setSystemValue('theme', 'theming-app'); - - if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app')) { - mkdir(\OC::$SERVERROOT . '/themes/theming-app'); - } - - if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core')) { - mkdir(\OC::$SERVERROOT . '/themes/theming-app/core'); - } - - if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core/img')) { - mkdir(\OC::$SERVERROOT . '/themes/theming-app/core/img'); - } - - if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core/css')) { - mkdir(\OC::$SERVERROOT . '/themes/theming-app/core/css'); - } - - if(!file_exists(\OC::$SERVERROOT . '/themes/theming-app/core/img/logo-icon.svg')) { - copy(\OC::$SERVERROOT . '/core/img/logo-icon.svg' ,\OC::$SERVERROOT . '/themes/theming-app/core/img/logo-icon.svg'); - } - } - -} diff --git a/apps/theming/lib/template.php b/apps/theming/lib/template.php index 177ead698898f..741fc1daa6a34 100644 --- a/apps/theming/lib/template.php +++ b/apps/theming/lib/template.php @@ -1,6 +1,7 @@ + * @copyright Copyright (c) 2016 Lukas Reschke * * @license GNU AGPL version 3 or any later version * @@ -19,10 +20,8 @@ * */ - namespace OCA\Theming; - use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; @@ -34,65 +33,55 @@ * * @package OCA\Theming */ -class Template { - +class Template extends \OC_Defaults { /** @var IConfig */ private $config; - /** @var IL10N */ private $l; - /** @var IURLGenerator */ private $urlGenerator; - - /** @var Init */ - private $init; - /** @var string */ private $name; - /** @var string */ private $url; - /** @var string */ private $slogan; - /** @var string */ private $color; - /** @var string */ - private $logoName; - /** * Template constructor. * * @param IConfig $config * @param IL10N $l * @param IURLGenerator $urlGenerator - * @param Init $init + * @param \OC_Defaults $defaults */ public function __construct(IConfig $config, IL10N $l, IURLGenerator $urlGenerator, - Init $init + \OC_Defaults $defaults ) { + parent::__construct(); $this->config = $config; $this->l = $l; $this->urlGenerator = $urlGenerator; - $this->init = $init; - $this->name = 'Nextcloud'; - $this->url = 'https://nextcloud.com'; - $this->slogan = $this->l->t('a safe home for all your data'); - $this->color = '#0082c9'; - $this->logoName = 'logo-icon.svg'; + $this->name = $defaults->getName(); + $this->url = $defaults->getBaseUrl(); + $this->slogan = $defaults->getSlogan(); + $this->color = $defaults->getMailHeaderColor(); } public function getName() { return $this->config->getAppValue('theming', 'name', $this->name); } + + public function getEntity() { + return $this->config->getAppValue('theming', 'name', $this->name); + } - public function getUrl() { + public function getBaseUrl() { return $this->config->getAppValue('theming', 'url', $this->url); } @@ -100,73 +89,57 @@ public function getSlogan() { return $this->config->getAppValue('theming', 'slogan', $this->slogan); } - public function getColor() { + public function getMailHeaderColor() { return $this->config->getAppValue('theming', 'color', $this->color); } - public function getLogoName() { - return $this->config->getAppValue('theming', 'logoName', $this->logoName); + /** + * Increases the cache buster key + */ + private function increaseCacheBuster() { + $cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0'); + $this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1); } /** - * update setting in the database + * Update setting in the database * - * @param $setting - * @param $value + * @param string $setting + * @param string $value */ public function set($setting, $value) { - $this->init->prepareThemeFolder(); $this->config->setAppValue('theming', $setting, $value); - $this->writeCSSFile(); + $this->increaseCacheBuster(); } /** - * revert settings to the default value + * Revert settings to the default value * * @param string $setting setting which should be reverted * @return string default value */ public function undo($setting) { - $returnValue = ''; - if ($this->$setting) { - $this->config->setAppValue('theming', $setting, $this->$setting); - $this->writeCSSFile(); - $returnValue = $this->$setting; + $this->config->deleteAppValue('theming', $setting); + $this->increaseCacheBuster(); + + switch ($setting) { + case 'name': + $returnValue = $this->getEntity(); + break; + case 'url': + $returnValue = $this->getBaseUrl(); + break; + case 'slogan': + $returnValue = $this->getSlogan(); + break; + case 'color': + $returnValue = $this->getMailHeaderColor(); + break; + default: + $returnValue = ''; + break; } return $returnValue; } - - /** - * write setting to a css file - */ - private function writeCSSFile() { - $logo = $this->getLogoName(); - $color = $this->getColor(); - - $css = " - #body-user #header, - #body-settings #header, - #body-public #header { - background-color: $color; - } - - - /* use logos from theme */ - #header .logo { - background-image: url('../img/$logo'); - width: 250px; - height: 121px; - } - #header .logo-icon { - background-image: url('../img/$logo'); - width: 62px; - height: 34px; - }"; - - $root = \OC::$SERVERROOT . '/themes/theming-app/core'; - - file_put_contents($root . '/css/styles.css', $css); - } - } diff --git a/apps/theming/settings/settings-admin.php b/apps/theming/settings/settings-admin.php index c79eb1475fb54..59da90a47f850 100644 --- a/apps/theming/settings/settings-admin.php +++ b/apps/theming/settings/settings-admin.php @@ -1,22 +1,22 @@ + * @copyright Copyright (c) 2016 Bjoern Schiessle + * @copyright Copyright (c) 2016 Lukas Reschke * - * @copyright Copyright (c) 2016, Bjoern Schiessle - * @license AGPL-3.0 + * @license GNU AGPL version 3 or any later version * - * This code is free software: you can redistribute it and/or modify + * 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 opinion) any later version. + * 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 + * 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 + * along with this program. If not, see . * */ @@ -25,35 +25,31 @@ $config = \OC::$server->getConfig(); $l = \OC::$server->getL10N('theming'); $urlGenerator = \OC::$server->getURLGenerator(); -$init = new \OCA\Theming\Init($config, \OC::$server->getLogger()); $theming = new \OCA\Theming\Template( $config, $l, \OC::$server->getURLGenerator(), - $init + new OC_Defaults() ); $themable = true; $errorMessage = ''; -$theme = $config->getSystemValue('theme', 'default'); +$theme = $config->getSystemValue('theme', ''); -if ($theme !== 'theming-app' && $theme !== 'default') { +if ($theme !== '') { $themable = false; $errorMessage = $l->t('You already use a custom theme'); -} elseif (!is_writable(\OC::$SERVERROOT . '/themes')) { - $themable = false; - $errorMessage = $l->t('Themes folder is read-only, please update the permissions to read-write'); } $template = new OCP\Template('theming', 'settings-admin'); $template->assign('themable', $themable); $template->assign('errorMessage', $errorMessage); -$template->assign('name', $theming->getName()); -$template->assign('url', $theming->getUrl()); +$template->assign('name', $theming->getEntity()); +$template->assign('url', $theming->getBaseUrl()); $template->assign('slogan', $theming->getSlogan()); -$template->assign('color', $theming->getColor()); +$template->assign('color', $theming->getMailHeaderColor()); $path = $urlGenerator->linkToRoute('theming.Theming.updateLogo'); $template->assign('uploadLogoRoute', $path); diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index 4e2277b0533e2..3a55deca0ce6f 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -14,27 +14,35 @@

- Name: + t('Name:')) ?>

- URL: + t('URL:')) ?>

- Slogan: + t('Slogan:')) ?>

- Color: + t('Color:')) ?>

-

+

- Logo: + t('Logo:')) ?> - - + + +
+

+

+

+ t('Login img.:')) ?> + + +

diff --git a/apps/theming/tests/lib/TemplateTest.php b/apps/theming/tests/lib/TemplateTest.php new file mode 100644 index 0000000000000..b9623e437b712 --- /dev/null +++ b/apps/theming/tests/lib/TemplateTest.php @@ -0,0 +1,301 @@ + + * + * @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 . + * + */ +namespace OCA\Theming\Tests; + +use OCA\Theming\Template; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use Test\TestCase; + +class TemplateTest extends TestCase { + /** @var IConfig */ + private $config; + /** @var IL10N */ + private $l10n; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var \OC_Defaults */ + private $defaults; + /** @var Template */ + private $template; + + public function setUp() { + $this->config = $this->getMock('\\OCP\\IConfig'); + $this->l10n = $this->getMock('\\OCP\\IL10N'); + $this->urlGenerator = $this->getMock('\\OCP\\IURLGenerator'); + $this->defaults = $this->getMockBuilder('\\OC_Defaults') + ->disableOriginalConstructor() + ->getMock(); + $this->defaults + ->expects($this->at(0)) + ->method('getName') + ->willReturn('Nextcloud'); + $this->defaults + ->expects($this->at(1)) + ->method('getBaseUrl') + ->willReturn('https://nextcloud.com/'); + $this->defaults + ->expects($this->at(2)) + ->method('getSlogan') + ->willReturn('Safe Data'); + $this->defaults + ->expects($this->at(3)) + ->method('getMailHeaderColor') + ->willReturn('#000'); + $this->template = new Template( + $this->config, + $this->l10n, + $this->urlGenerator, + $this->defaults + ); + + return parent::setUp(); + } + + public function testGetNameWithDefault() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'name', 'Nextcloud') + ->willReturn('Nextcloud'); + + $this->assertEquals('Nextcloud', $this->template->getName()); + } + + public function testGetNameWithCustom() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'name', 'Nextcloud') + ->willReturn('MyCustomCloud'); + + $this->assertEquals('MyCustomCloud', $this->template->getName()); + } + + public function testGetEntityWithDefault() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'name', 'Nextcloud') + ->willReturn('Nextcloud'); + + $this->assertEquals('Nextcloud', $this->template->getEntity()); + } + + public function testGetEntityWithCustom() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'name', 'Nextcloud') + ->willReturn('MyCustomCloud'); + + $this->assertEquals('MyCustomCloud', $this->template->getEntity()); + } + + public function testGetBaseUrlWithDefault() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'url', 'https://nextcloud.com/') + ->willReturn('https://nextcloud.com/'); + + $this->assertEquals('https://nextcloud.com/', $this->template->getBaseUrl()); + } + + public function testGetBaseUrlWithCustom() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'url', 'https://nextcloud.com/') + ->willReturn('https://example.com/'); + + $this->assertEquals('https://example.com/', $this->template->getBaseUrl()); + } + + public function testGetSloganWithDefault() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'slogan', 'Safe Data') + ->willReturn('Safe Data'); + + $this->assertEquals('Safe Data', $this->template->getSlogan()); + } + + public function testGetSloganWithCustom() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'slogan', 'Safe Data') + ->willReturn('My custom Slogan'); + + $this->assertEquals('My custom Slogan', $this->template->getSlogan()); + } + + public function testGetMailHeaderColorWithDefault() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'color', '#000') + ->willReturn('#000'); + + $this->assertEquals('#000', $this->template->getMailHeaderColor()); + } + + public function testGetMailHeaderColorWithCustom() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'color', '#000') + ->willReturn('#fff'); + + $this->assertEquals('#fff', $this->template->getMailHeaderColor()); + } + + public function testSet() { + $this->config + ->expects($this->at(0)) + ->method('setAppValue') + ->with('theming', 'MySetting', 'MyValue'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); + $this->config + ->expects($this->at(2)) + ->method('setAppValue') + ->with('theming', 'cachebuster', 16); + + $this->template->set('MySetting', 'MyValue'); + } + + public function testUndoName() { + $this->config + ->expects($this->at(0)) + ->method('deleteAppValue') + ->with('theming', 'name'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); + $this->config + ->expects($this->at(2)) + ->method('setAppValue') + ->with('theming', 'cachebuster', 16); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'name', 'Nextcloud') + ->willReturn('Nextcloud'); + + $this->assertSame('Nextcloud', $this->template->undo('name')); + } + + public function testUndoBaseUrl() { + $this->config + ->expects($this->at(0)) + ->method('deleteAppValue') + ->with('theming', 'url'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); + $this->config + ->expects($this->at(2)) + ->method('setAppValue') + ->with('theming', 'cachebuster', 16); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'url', 'https://nextcloud.com/') + ->willReturn('https://nextcloud.com/'); + + $this->assertSame('https://nextcloud.com/', $this->template->undo('url')); + } + + public function testUndoSlogan() { + $this->config + ->expects($this->at(0)) + ->method('deleteAppValue') + ->with('theming', 'slogan'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); + $this->config + ->expects($this->at(2)) + ->method('setAppValue') + ->with('theming', 'cachebuster', 16); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'slogan', 'Safe Data') + ->willReturn('Safe Data'); + + $this->assertSame('Safe Data', $this->template->undo('slogan')); + } + + public function testUndoColor() { + $this->config + ->expects($this->at(0)) + ->method('deleteAppValue') + ->with('theming', 'color'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); + $this->config + ->expects($this->at(2)) + ->method('setAppValue') + ->with('theming', 'cachebuster', 16); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'color', '#000') + ->willReturn('#000'); + + $this->assertSame('#000', $this->template->undo('color')); + } + + public function testUndoDefaultAction() { + $this->config + ->expects($this->at(0)) + ->method('deleteAppValue') + ->with('theming', 'defaultitem'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); + $this->config + ->expects($this->at(2)) + ->method('setAppValue') + ->with('theming', 'cachebuster', 16); + + $this->assertSame('', $this->template->undo('defaultitem')); + } +} diff --git a/apps/theming/tests/lib/controller/ThemingControllerTest.php b/apps/theming/tests/lib/controller/ThemingControllerTest.php new file mode 100644 index 0000000000000..82aa7d13818ee --- /dev/null +++ b/apps/theming/tests/lib/controller/ThemingControllerTest.php @@ -0,0 +1,405 @@ + + * + * @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 . + * + */ +namespace OCA\Theming\Tests\Controller; + +use OCA\Theming\Controller\ThemingController; +use OCA\Theming\Template; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IRequest; +use Test\TestCase; + +class ThemingControllerTest extends TestCase { + /** @var IRequest */ + private $request; + /** @var IConfig */ + private $config; + /** @var Template */ + private $template; + /** @var IL10N */ + private $l10n; + /** @var ThemingController */ + private $themingController; + + public function setUp() { + $this->request = $this->getMock('\\OCP\\IRequest'); + $this->config = $this->getMock('\\OCP\\IConfig'); + $this->template = $this->getMockBuilder('\\OCA\\Theming\\Template') + ->disableOriginalConstructor()->getMock(); + $this->l10n = $this->getMock('\\OCP\\IL10N'); + $this->themingController = new ThemingController( + 'theming', + $this->request, + $this->config, + $this->template, + $this->l10n + ); + + return parent::setUp(); + } + + public function testUpdateStylesheet() { + $this->template + ->expects($this->once()) + ->method('set') + ->with('MySetting', 'MyValue'); + $this->l10n + ->expects($this->once()) + ->method('t') + ->with('Saved') + ->willReturn('Saved'); + + $expected = new DataResponse( + [ + 'data' => + [ + 'message' => 'Saved', + ], + 'status' => 'success' + ] + ); + $this->assertEquals($expected, $this->themingController->updateStylesheet('MySetting', 'MyValue')); + } + + public function testUpdateLogoNoData() { + $this->request + ->expects($this->at(0)) + ->method('getUploadedFile') + ->with('uploadlogo') + ->willReturn(null); + $this->request + ->expects($this->at(1)) + ->method('getUploadedFile') + ->with('upload-login-background') + ->willReturn(null); + $this->l10n + ->expects($this->once()) + ->method('t') + ->with('No file uploaded') + ->willReturn('No file uploaded'); + + $expected = new DataResponse( + [ + 'data' => + [ + 'message' => 'No file uploaded', + ], + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + + $this->assertEquals($expected, $this->themingController->updateLogo()); + } + + public function testUpdateLogoNormalLogoUpload() { + $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg'; + $destination = \OC::$server->getTempManager()->getTemporaryFolder(); + + touch($tmpLogo); + $this->request + ->expects($this->at(0)) + ->method('getUploadedFile') + ->with('uploadlogo') + ->willReturn([ + 'tmp_name' => $tmpLogo, + 'type' => 'text/svg', + 'name' => 'logo.svg', + ]); + $this->request + ->expects($this->at(1)) + ->method('getUploadedFile') + ->with('upload-login-background') + ->willReturn(null); + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('datadirectory', \OC::$SERVERROOT . '/data') + ->willReturn($destination); + $this->l10n + ->expects($this->once()) + ->method('t') + ->with('Saved') + ->willReturn('Saved'); + + $expected = new DataResponse( + [ + 'data' => + [ + 'name' => 'logo.svg', + 'message' => 'Saved', + ], + 'status' => 'success' + ] + ); + + $this->assertEquals($expected, $this->themingController->updateLogo()); + } + + public function testUpdateLogoLoginScreenUpload() { + $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg'; + $destination = \OC::$server->getTempManager()->getTemporaryFolder(); + + touch($tmpLogo); + $this->request + ->expects($this->at(0)) + ->method('getUploadedFile') + ->with('uploadlogo') + ->willReturn(null); + $this->request + ->expects($this->at(1)) + ->method('getUploadedFile') + ->with('upload-login-background') + ->willReturn([ + 'tmp_name' => $tmpLogo, + 'type' => 'text/svg', + 'name' => 'logo.svg', + ]); + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('datadirectory', \OC::$SERVERROOT . '/data') + ->willReturn($destination); + $this->l10n + ->expects($this->once()) + ->method('t') + ->with('Saved') + ->willReturn('Saved'); + + $expected = new DataResponse( + [ + 'data' => + [ + 'name' => 'logo.svg', + 'message' => 'Saved', + ], + 'status' => 'success' + ] + ); + $this->assertEquals($expected, $this->themingController->updateLogo()); + } + + public function testUndo() { + $this->l10n + ->expects($this->once()) + ->method('t') + ->with('Saved') + ->willReturn('Saved'); + $this->template + ->expects($this->once()) + ->method('undo') + ->with('MySetting') + ->willReturn('MyValue'); + + $expected = new DataResponse( + [ + 'data' => + [ + 'value' => 'MyValue', + 'message' => 'Saved', + ], + 'status' => 'success' + ] + ); + $this->assertEquals($expected, $this->themingController->undo('MySetting')); + } + + public function testGetLogoNotExistent() { + $expected = new DataResponse(); + $this->assertEquals($expected, $this->themingController->getLogo()); + } + + public function testGetLogo() { + $dataFolder = \OC::$server->getTempManager()->getTemporaryFolder(); + $tmpLogo = $dataFolder . '/themedinstancelogo'; + touch($tmpLogo); + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('datadirectory', \OC::$SERVERROOT . '/data/') + ->willReturn($dataFolder); + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'logoMime', '') + ->willReturn('text/svg'); + + @$expected = new Http\StreamResponse($tmpLogo); + $expected->cacheFor(3600); + $expected->addHeader('Content-Disposition', 'attachment'); + $expected->addHeader('Content-Type', 'text/svg'); + @$this->assertEquals($expected, $this->themingController->getLogo()); + } + + + public function testGetLoginBackgroundNotExistent() { + $expected = new DataResponse(); + $this->assertEquals($expected, $this->themingController->getLoginBackground()); + } + + public function testGetLoginBackground() { + $dataFolder = \OC::$server->getTempManager()->getTemporaryFolder(); + $tmpLogo = $dataFolder . '/themedbackgroundlogo'; + touch($tmpLogo); + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('datadirectory', \OC::$SERVERROOT . '/data/') + ->willReturn($dataFolder); + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'backgroundMime', '') + ->willReturn('image/png'); + + @$expected = new Http\StreamResponse($tmpLogo); + $expected->cacheFor(3600); + $expected->addHeader('Content-Disposition', 'attachment'); + $expected->addHeader('Content-Type', 'image/png'); + @$this->assertEquals($expected, $this->themingController->getLoginBackground()); + } + + public function testGetStylesheetWithOnlyColor() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('0'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'color', '') + ->willReturn('#fff'); + $this->config + ->expects($this->at(2)) + ->method('getAppValue') + ->with('theming', 'logoMime', '') + ->willReturn(''); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'backgroundMime', '') + ->willReturn(''); + + $expected = new Http\DataDownloadResponse('#body-user #header,#body-settings #header,#body-public #header {background-color: #fff}', 'style.css', 'text/css'); + $expected->cacheFor(3600); + @$this->assertEquals($expected, $this->themingController->getStylesheet()); + } + + public function testGetStylesheetWithOnlyHeaderLogo() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('0'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'color', '') + ->willReturn(''); + $this->config + ->expects($this->at(2)) + ->method('getAppValue') + ->with('theming', 'logoMime', '') + ->willReturn('image/png'); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'backgroundMime', '') + ->willReturn(''); + + $expected = new Http\DataDownloadResponse('#header .logo { + background-image: url(\'./logo?v=0\'); + } + #header .logo-icon { + background-image: url(\'./logo?v=0\'); + background-size: 62px 34px; + }', 'style.css', 'text/css'); + $expected->cacheFor(3600); + @$this->assertEquals($expected, $this->themingController->getStylesheet()); + } + + public function testGetStylesheetWithOnlyBackgroundLogin() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('0'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'color', '') + ->willReturn(''); + $this->config + ->expects($this->at(2)) + ->method('getAppValue') + ->with('theming', 'logoMime', '') + ->willReturn(''); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'backgroundMime', '') + ->willReturn('text/svg'); + + $expected = new Http\DataDownloadResponse('#body-login { + background-image: url(\'./loginbackground?v=0\'); + }', 'style.css', 'text/css'); + $expected->cacheFor(3600); + @$this->assertEquals($expected, $this->themingController->getStylesheet()); + } + + public function testGetStylesheetWithAllCombined() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('theming', 'cachebuster', '0') + ->willReturn('0'); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('theming', 'color', '') + ->willReturn('#abc'); + $this->config + ->expects($this->at(2)) + ->method('getAppValue') + ->with('theming', 'logoMime', '') + ->willReturn('text/svg'); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('theming', 'backgroundMime', '') + ->willReturn('image/png'); + + $expected = new Http\DataDownloadResponse('#body-user #header,#body-settings #header,#body-public #header {background-color: #abc}#header .logo { + background-image: url(\'./logo?v=0\'); + } + #header .logo-icon { + background-image: url(\'./logo?v=0\'); + background-size: 62px 34px; + }#body-login { + background-image: url(\'./loginbackground?v=0\'); + }', 'style.css', 'text/css'); + $expected->cacheFor(3600); + @$this->assertEquals($expected, $this->themingController->getStylesheet()); + } + +} diff --git a/core/js/config.php b/core/js/config.php index dc84d1cf2bf22..197047ed8b800 100644 --- a/core/js/config.php +++ b/core/js/config.php @@ -43,7 +43,7 @@ $l = \OC::$server->getL10N('core'); // Enable OC_Defaults support -$defaults = new OC_Defaults(); +$defaults = \OC::$server->getThemingDefaults(); // Get the config $apps_paths = array(); diff --git a/core/shipped.json b/core/shipped.json index a3abe22d8d5d0..ed9cf52fa72d4 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -32,6 +32,7 @@ "systemtags", "systemtags_management", "templateeditor", + "theming", "updatenotification", "user_external", "user_ldap", diff --git a/lib/private/Server.php b/lib/private/Server.php index 8345a0b66e09e..df7bb619208fc 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -78,6 +78,7 @@ use OC\Security\TrustedDomainHelper; use OC\Session\CryptoWrapper; use OC\Tagging\TagMapper; +use OCA\Theming\Template; use OCP\IL10N; use OCP\IServerContainer; use OCP\Security\IContentSecurityPolicyManager; @@ -618,6 +619,17 @@ public function __construct($webRoot, \OC\Config $config) { $factory = new $factoryClass($this); return $factory->getManager(); }); + $this->registerService('ThemingDefaults', function(Server $c) { + if($this->getAppManager()->isInstalled('theming')) { + return new Template( + $this->getConfig(), + $this->getL10N('theming'), + $this->getURLGenerator(), + new \OC_Defaults() + ); + } + return new \OC_Defaults(); + }); $this->registerService('EventDispatcher', function () { return new EventDispatcher(); }); @@ -1288,6 +1300,14 @@ public function getCommentsManager() { return $this->query('CommentsManager'); } + /** + * @internal Not public by intention. + * @return \OC_Defaults + */ + public function getThemingDefaults() { + return $this->query('ThemingDefaults'); + } + /** * @return \OC\IntegrityCheck\Checker */ diff --git a/lib/private/legacy/defaults.php b/lib/private/legacy/defaults.php index f0cc4c91851ad..2a97cfe89edde 100644 --- a/lib/private/legacy/defaults.php +++ b/lib/private/legacy/defaults.php @@ -31,13 +31,8 @@ class OC_Defaults { private $theme; - - /** @var \OCP\IL10N */ private $l; - /** @var \OCA\Theming\Template */ - private $template; - private $defaultEntity; private $defaultName; private $defaultTitle; @@ -54,45 +49,21 @@ class OC_Defaults { function __construct() { $this->l = \OC::$server->getL10N('lib'); - $config = \OC::$server->getConfig(); - - - try { - $themingAppEnabled = $config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming'); - } catch (\Exception $e) { - $themingAppEnabled = false; - } - - $config = \OC::$server->getConfig(); - - if ($themingAppEnabled) { - $this->template = new \OCA\Theming\Template( - $config, - $this->l, - \OC::$server->getURLGenerator(), - new \OCA\Theming\Init($config, \OC::$server->getLogger()) - ); - $this->defaultName = $this->template->getName(); /* short name, used when referring to the software */ - $this->defaultBaseUrl = $this->template->getUrl(); - $this->defaultSlogan = $this->template->getSlogan(); - $this->defaultMailHeaderColor = $this->template->getColor(); /* header color of mail notifications */ - } else { - $this->defaultName = 'Nextcloud'; - $this->defaultBaseUrl = 'https://nextcloud.com'; - $this->defaultSlogan = $this->l->t('a safe home for all your data'); - $this->defaultMailHeaderColor = '#0082c9'; /* header color of mail notifications */ - } $version = \OCP\Util::getVersion(); $this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */ + $this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */ $this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */ + $this->defaultBaseUrl = 'https://nextcloud.com'; $this->defaultSyncClientUrl = 'https://nextcloud.com/install'; $this->defaultiOSClientUrl = 'https://itunes.apple.com/us/app/owncloud/id543672169?mt=8'; $this->defaultiTunesAppId = '543672169'; $this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.owncloud.android'; $this->defaultDocBaseUrl = 'https://doc.owncloud.org'; $this->defaultDocVersion = $version[0] . '.' . $version[1]; // used to generate doc links + $this->defaultSlogan = $this->l->t('a safe home for all your data'); $this->defaultLogoClaim = ''; + $this->defaultMailHeaderColor = '#0082c9'; /* header color of mail notifications */ $themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php'; if (file_exists($themePath)) { diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php index 5023e3a60c801..e295650809065 100644 --- a/lib/private/legacy/template.php +++ b/lib/private/legacy/template.php @@ -80,7 +80,7 @@ public function __construct( $app, $name, $renderAs = "", $registerCall = true ) $parts = explode('/', $app); // fix translation when app is something like core/lostpassword $l10n = \OC::$server->getL10N($parts[0]); - $themeDefaults = new OC_Defaults(); + $themeDefaults = \OC::$server->getThemingDefaults(); list($path, $template) = $this->findTemplate($theme, $app, $name); From f225c5dae24897e02c5c161ccdf6b8f262df0e92 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 21 Jun 2016 21:43:19 +0200 Subject: [PATCH 18/81] Check if server is installed AppManager has a dependency on Nc being installed --- lib/private/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/Server.php b/lib/private/Server.php index df7bb619208fc..15291c9c8d4b0 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -620,7 +620,7 @@ public function __construct($webRoot, \OC\Config $config) { return $factory->getManager(); }); $this->registerService('ThemingDefaults', function(Server $c) { - if($this->getAppManager()->isInstalled('theming')) { + if($this->getConfig()->getSystemValue('installed', false) && $this->getAppManager()->isInstalled('theming')) { return new Template( $this->getConfig(), $this->getL10N('theming'), From 1e93c265b0898f6b717348f6c37164e1133e1c97 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 21 Jun 2016 21:44:00 +0200 Subject: [PATCH 19/81] Fix indentation --- apps/theming/appinfo/routes.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/theming/appinfo/routes.php b/apps/theming/appinfo/routes.php index dbbae372ffd19..ac0463e2c26a2 100644 --- a/apps/theming/appinfo/routes.php +++ b/apps/theming/appinfo/routes.php @@ -49,9 +49,9 @@ 'verb' => 'GET', ], [ - 'name' => 'Theming#getLoginBackground', - 'url' => '/loginbackground', - 'verb' => 'GET', + 'name' => 'Theming#getLoginBackground', + 'url' => '/loginbackground', + 'verb' => 'GET', ], ))); From 7c232d5edfd948187dfa4fceef4fe152c9e15648 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 21 Jun 2016 21:46:27 +0200 Subject: [PATCH 20/81] Disable drop zone Otherwise dropping something somewhere can by mistake upload the file and make it available --- apps/theming/js/settings-admin.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 1acd6a97e967d..8ce76a2ccf225 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -52,6 +52,7 @@ $(document).ready(function () { var uploadParamsLogo = { pasteZone: null, + dropZone: null, done: function (e, response) { preview('logoMime', response.result.data.name); OC.msg.finishedSaving('#theming_settings_msg', response.result); @@ -65,6 +66,7 @@ $(document).ready(function () { }; var uploadParamsLogin = { pasteZone: null, + dropZone: null, done: function (e, response) { preview('backgroundMime', response.result.data.name); OC.msg.finishedSaving('#theming_settings_msg', response.result); From ca364292894a85ceb4a1f959b7e39ceb35e7da3d Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 21 Jun 2016 21:59:24 +0200 Subject: [PATCH 21/81] Adjust integration test The app is now enabled by default --- build/integration/features/provisioning-v1.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/build/integration/features/provisioning-v1.feature b/build/integration/features/provisioning-v1.feature index 1e0df08a631ba..135c67dc3a675 100644 --- a/build/integration/features/provisioning-v1.feature +++ b/build/integration/features/provisioning-v1.feature @@ -293,6 +293,7 @@ Feature: provisioning | files_versions | | provisioning_api | | systemtags | + | theming | | updatenotification | Scenario: get app info From 61cba10816a226223e8130c9128408838038ecbc Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 22 Jun 2016 13:44:33 +0200 Subject: [PATCH 22/81] scale preview image --- apps/theming/js/settings-admin.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 8ce76a2ccf225..cd650fc0acaea 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -6,7 +6,7 @@ * * This code 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 + * published by the Free Software Foundation, either version 3 of the * License, or (at your opinion) any later version. * * This program is distributed in the hope that it will be useful, @@ -42,8 +42,10 @@ function preview(setting, value) { var logos = document.getElementsByClassName('logo-icon'); if(value !== '') { logos[0].style.background = "url('" + OC.generateUrl('/apps/theming/logo') + "')"; + logos[0].style.backgroundSize = "62px 34px"; } else { logos[0].style.background = "url('" + OC.getRootPath() + '/core/img/logo-icon.svg'+"')"; + logos[0].style.backgroundSize = "62px 34px"; } } } @@ -78,7 +80,7 @@ $(document).ready(function () { OC.msg.finishedSaving('#theming_settings_msg', response); } }; - + $('#uploadlogo').fileupload(uploadParamsLogo); $('#upload-login-background').fileupload(uploadParamsLogin); @@ -109,7 +111,7 @@ $(document).ready(function () { $('#theming-color').change(function (e) { setThemingValue('color', '#' + $(this).val()); }); - + $('.theme-undo').click(function (e) { var setting = $(this).data('setting'); OC.msg.startSaving('#theming_settings_msg'); From 0e30db440e077beddcdc1bacc8fa4c2bc8a7dbe6 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 22 Jun 2016 14:04:54 +0200 Subject: [PATCH 23/81] make sure that the preview gets updated every time a new image gets uploaded --- apps/theming/js/settings-admin.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index cd650fc0acaea..86c22471adbcd 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -40,11 +40,12 @@ function preview(setting, value) { if (setting === 'logoMime') { console.log(setting); var logos = document.getElementsByClassName('logo-icon'); + var timestamp = new Date().getTime(); if(value !== '') { - logos[0].style.background = "url('" + OC.generateUrl('/apps/theming/logo') + "')"; + logos[0].style.background = "url('" + OC.generateUrl('/apps/theming/logo') + "?v" + timestamp + "')"; logos[0].style.backgroundSize = "62px 34px"; } else { - logos[0].style.background = "url('" + OC.getRootPath() + '/core/img/logo-icon.svg'+"')"; + logos[0].style.background = "url('" + OC.getRootPath() + '/core/img/logo-icon.svg?v' + timestamp +"')"; logos[0].style.backgroundSize = "62px 34px"; } } From 973fe7af1b10df64367dc2508a3fc121f53268e5 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 23 Jun 2016 12:05:42 +0200 Subject: [PATCH 24/81] design and layout fixes for Theming app --- apps/theming/css/settings-admin.css | 10 +++++-- apps/theming/templates/settings-admin.php | 34 ++++++++++++++--------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/apps/theming/css/settings-admin.css b/apps/theming/css/settings-admin.css index 931e4d4508b41..53214b245c639 100644 --- a/apps/theming/css/settings-admin.css +++ b/apps/theming/css/settings-admin.css @@ -8,19 +8,25 @@ #theming .theme-undo { cursor: pointer; + opacity: .5; + padding: 9px; + vertical-align: bottom; } #theming .icon { display: inline-block; } -#theming .theming-label { - min-width: 6em; +#theming label span { display: inline-block; + min-width: 90px; + padding: 8px 0px; } #theming .icon-upload { display: inline-flex; + padding: 8px; + margin: 0; } div#theming_settings_msg { diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index 3a55deca0ce6f..f802b947c8008 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -14,35 +14,43 @@

- t('Name:')) ?> - + +

- t('URL:')) ?> - + +

- t('Slogan:')) ?> - + +

- t('Color:')) ?> - + +

- t('Logo:')) ?> + - +

-

+

- t('Login img.:')) ?> + - +

From 1c5b9c008a1e83a96f4a833d59c52ca8d7142da7 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 27 Jun 2016 10:34:08 +0200 Subject: [PATCH 25/81] Replace OC_Defaults with \OC::$server->getThemingDefaults() --- apps/theming/settings/settings-admin.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/theming/settings/settings-admin.php b/apps/theming/settings/settings-admin.php index 59da90a47f850..a7643960adc44 100644 --- a/apps/theming/settings/settings-admin.php +++ b/apps/theming/settings/settings-admin.php @@ -26,12 +26,7 @@ $l = \OC::$server->getL10N('theming'); $urlGenerator = \OC::$server->getURLGenerator(); -$theming = new \OCA\Theming\Template( - $config, - $l, - \OC::$server->getURLGenerator(), - new OC_Defaults() -); +$theming = \OC::$server->getThemingDefaults(); $themable = true; $errorMessage = ''; From 050f373d2559c3f4c79d933702d7478d0b579205 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 27 Jun 2016 10:47:44 +0200 Subject: [PATCH 26/81] Use stream instead of rename --- .../lib/controller/themingcontroller.php | 14 ++++-- .../lib/controller/ThemingControllerTest.php | 45 ++++++++++++++----- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/apps/theming/lib/controller/themingcontroller.php b/apps/theming/lib/controller/themingcontroller.php index dd4ff82195160..995f929b510c7 100644 --- a/apps/theming/lib/controller/themingcontroller.php +++ b/apps/theming/lib/controller/themingcontroller.php @@ -26,6 +26,7 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\Files\IRootFolder; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; @@ -44,6 +45,8 @@ class ThemingController extends Controller { private $l; /** @var IConfig */ private $config; + /** @var IRootFolder */ + private $rootFolder; /** * ThemingController constructor. @@ -53,19 +56,22 @@ class ThemingController extends Controller { * @param IConfig $config * @param Template $template * @param IL10N $l + * @param IRootFolder $rootFolder */ public function __construct( $appName, IRequest $request, IConfig $config, Template $template, - IL10N $l + IL10N $l, + IRootFolder $rootFolder ) { parent::__construct($appName, $request); $this->template = $template; $this->l = $l; $this->config = $config; + $this->rootFolder = $rootFolder; } /** @@ -106,12 +112,14 @@ public function updateLogo() { } $name = ''; if(!empty($newLogo)) { - rename($newLogo['tmp_name'], $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedinstancelogo'); + $target = $this->rootFolder->newFile('themedinstancelogo'); + stream_copy_to_stream(fopen($newLogo['tmp_name'], 'r'), $target->fopen('w')); $this->template->set('logoMime', $newLogo['type']); $name = $newLogo['name']; } if(!empty($newBackgroundLogo)) { - rename($newBackgroundLogo['tmp_name'], $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedbackgroundlogo'); + $target = $this->rootFolder->newFile('themedbackgroundlogo'); + stream_copy_to_stream(fopen($newBackgroundLogo['tmp_name'], 'r'), $target->fopen('w')); $this->template->set('backgroundMime', $newBackgroundLogo['type']); $name = $newBackgroundLogo['name']; } diff --git a/apps/theming/tests/lib/controller/ThemingControllerTest.php b/apps/theming/tests/lib/controller/ThemingControllerTest.php index 82aa7d13818ee..7fba27316a227 100644 --- a/apps/theming/tests/lib/controller/ThemingControllerTest.php +++ b/apps/theming/tests/lib/controller/ThemingControllerTest.php @@ -24,6 +24,7 @@ use OCA\Theming\Template; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\Files\IRootFolder; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; @@ -40,6 +41,8 @@ class ThemingControllerTest extends TestCase { private $l10n; /** @var ThemingController */ private $themingController; + /** @var IRootFolder */ + private $rootFolder; public function setUp() { $this->request = $this->getMock('\\OCP\\IRequest'); @@ -47,12 +50,15 @@ public function setUp() { $this->template = $this->getMockBuilder('\\OCA\\Theming\\Template') ->disableOriginalConstructor()->getMock(); $this->l10n = $this->getMock('\\OCP\\IL10N'); + $this->rootFolder = $this->getMock('\\OCP\\Files\\IRootFolder'); + $this->themingController = new ThemingController( 'theming', $this->request, $this->config, $this->template, - $this->l10n + $this->l10n, + $this->rootFolder ); return parent::setUp(); @@ -130,16 +136,24 @@ public function testUpdateLogoNormalLogoUpload() { ->method('getUploadedFile') ->with('upload-login-background') ->willReturn(null); - $this->config - ->expects($this->at(0)) - ->method('getSystemValue') - ->with('datadirectory', \OC::$SERVERROOT . '/data') - ->willReturn($destination); $this->l10n ->expects($this->once()) ->method('t') ->with('Saved') ->willReturn('Saved'); + $file = $this->getMockBuilder('\\OCP\\Files\\File') + ->disableOriginalConstructor() + ->getMock(); + $this->rootFolder + ->expects($this->once()) + ->method('newFile') + ->with('themedinstancelogo') + ->willReturn($file); + $file + ->expects($this->once()) + ->method('fopen') + ->with('w') + ->willReturn(fopen($destination . '/themedinstancelogo', 'w')); $expected = new DataResponse( [ @@ -174,16 +188,25 @@ public function testUpdateLogoLoginScreenUpload() { 'type' => 'text/svg', 'name' => 'logo.svg', ]); - $this->config - ->expects($this->at(0)) - ->method('getSystemValue') - ->with('datadirectory', \OC::$SERVERROOT . '/data') - ->willReturn($destination); $this->l10n ->expects($this->once()) ->method('t') ->with('Saved') ->willReturn('Saved'); + $file = $this->getMockBuilder('\\OCP\\Files\\File') + ->disableOriginalConstructor() + ->getMock(); + $this->rootFolder + ->expects($this->once()) + ->method('newFile') + ->with('themedbackgroundlogo') + ->willReturn($file); + $file + ->expects($this->once()) + ->method('fopen') + ->with('w') + ->willReturn(fopen($destination . '/themedbackgroundlogo', 'w')); + $expected = new DataResponse( [ From 468474141fe5b2a362b613ae621313ae917ab570 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 27 Jun 2016 10:48:23 +0200 Subject: [PATCH 27/81] Add comment to "getMailHeaderColor" --- apps/theming/lib/template.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/theming/lib/template.php b/apps/theming/lib/template.php index 741fc1daa6a34..01e3ca8b7c0ee 100644 --- a/apps/theming/lib/template.php +++ b/apps/theming/lib/template.php @@ -89,6 +89,11 @@ public function getSlogan() { return $this->config->getAppValue('theming', 'slogan', $this->slogan); } + /** + * Color that is used for the header as well as for mail headers + * + * @return string + */ public function getMailHeaderColor() { return $this->config->getAppValue('theming', 'color', $this->color); } From 95344d0625dff314fb204cddbfea65f743b1011b Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 27 Jun 2016 10:50:10 +0200 Subject: [PATCH 28/81] Quickfix: do not lazy load auth mechanisms for ext storages Some auth mechanisms like SessionCredentials need to register hooks early, so they cannot be lazy loaded. --- apps/files_external/lib/AppInfo/Application.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/files_external/lib/AppInfo/Application.php b/apps/files_external/lib/AppInfo/Application.php index f78411038fa77..b2eaf225e9e6a 100644 --- a/apps/files_external/lib/AppInfo/Application.php +++ b/apps/files_external/lib/AppInfo/Application.php @@ -52,6 +52,10 @@ public function __construct(array $urlParams = array()) { $backendService->registerBackendProvider($this); $backendService->registerAuthMechanismProvider($this); + // force-load auth mechanisms since some will register hooks + // TODO: obsolete these and use the TokenProvider to get the user's password from the session + $this->getAuthMechanisms(); + // app developers: do NOT depend on this! it will disappear with oC 9.0! \OC::$server->getEventDispatcher()->dispatch( 'OCA\\Files_External::loadAdditionalBackends' From 112bc07e400346096ca29a0ce0903eff0e210c15 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Mon, 27 Jun 2016 16:50:10 +0200 Subject: [PATCH 29/81] Add app:check-code for already compatible apps * admin_audit, comments, federation * removed not needed call to OC_Util::checkAdminUser() (is already done by the request handler before) --- .travis.yml | 3 +++ apps/encryption/settings/settings-admin.php | 2 -- apps/federatedfilesharing/settings-admin.php | 2 -- apps/federation/settings/settings-admin.php | 2 -- apps/files/admin.php | 2 -- apps/files/download.php | 3 --- apps/files/list.php | 3 --- apps/files_external/settings.php | 2 -- apps/user_ldap/settings.php | 2 -- 9 files changed, 3 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 242ba71e39502..15413d3413eea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ install: script: - sh -c "if [ '$TC' = 'syntax' ]; then composer install && lib/composer/bin/parallel-lint --exclude lib/composer/jakub-onderka/ --exclude 3rdparty/symfony/polyfill-php70/Resources/stubs/ --exclude 3rdparty/patchwork/utf8/src/Patchwork/Utf8/Bootup/ --exclude 3rdparty/paragonie/random_compat/lib/ --exclude lib/composer/composer/autoload_static.php --exclude 3rdparty/composer/autoload_static.php .; fi" + - sh -c "if [ '$TC' = 'app:check-code' ]; then ./occ app:check-code admin_audit; ./occ app:check-code comments; ./occ app:check-code federation; fi" - sh -c "if [ '$TEST_DAV' != '1' ]; then echo \"Not testing DAV\"; fi" - sh -c "if [ '$TEST_DAV' = '1' ]; then echo \"Testing DAV\"; fi" @@ -51,5 +52,7 @@ matrix: env: DB=sqlite;TC=syntax;TEST_DAV=0 - php: 7.0 env: DB=sqlite;TC=syntax;TEST_DAV=0 + - php: 5.4 + env: DB=sqlite;TC=app:check-code;TEST_DAV=0 fast_finish: true diff --git a/apps/encryption/settings/settings-admin.php b/apps/encryption/settings/settings-admin.php index 87de11bba0f64..bca3d5168a0a3 100644 --- a/apps/encryption/settings/settings-admin.php +++ b/apps/encryption/settings/settings-admin.php @@ -22,8 +22,6 @@ * */ -\OC_Util::checkAdminUser(); - $tmpl = new OCP\Template('encryption', 'settings-admin'); $crypt = new \OCA\Encryption\Crypto\Crypt( diff --git a/apps/federatedfilesharing/settings-admin.php b/apps/federatedfilesharing/settings-admin.php index 33851129942ae..9875dcf3b5b8d 100644 --- a/apps/federatedfilesharing/settings-admin.php +++ b/apps/federatedfilesharing/settings-admin.php @@ -22,8 +22,6 @@ use OCA\FederatedFileSharing\AppInfo\Application; -\OC_Util::checkAdminUser(); - $app = new Application('federatedfilesharing'); $federatedShareProvider = $app->getFederatedShareProvider(); diff --git a/apps/federation/settings/settings-admin.php b/apps/federation/settings/settings-admin.php index b5fd7710efcc7..4511ff954b52c 100644 --- a/apps/federation/settings/settings-admin.php +++ b/apps/federation/settings/settings-admin.php @@ -19,8 +19,6 @@ * */ -\OC_Util::checkAdminUser(); - $template = new OCP\Template('federation', 'settings-admin'); $dbHandler = new \OCA\Federation\DbHandler( diff --git a/apps/files/admin.php b/apps/files/admin.php index 60f041a400b66..48a6100838f14 100644 --- a/apps/files/admin.php +++ b/apps/files/admin.php @@ -27,8 +27,6 @@ * */ -OCP\User::checkAdminUser(); - $htaccessWorking=(getenv('htaccessWorking')=='true'); $upload_max_filesize = OC::$server->getIniWrapper()->getBytes('upload_max_filesize'); $post_max_size = OC::$server->getIniWrapper()->getBytes('post_max_size'); diff --git a/apps/files/download.php b/apps/files/download.php index 38ac2a074c377..da01f98ed6234 100644 --- a/apps/files/download.php +++ b/apps/files/download.php @@ -26,9 +26,6 @@ * */ -// Check if we are a user -OCP\User::checkLoggedIn(); - $filename = $_GET["file"]; if(!\OC\Files\Filesystem::file_exists($filename)) { diff --git a/apps/files/list.php b/apps/files/list.php index 6d2c463a2d912..2d7a304df2426 100644 --- a/apps/files/list.php +++ b/apps/files/list.php @@ -20,9 +20,6 @@ * */ -// Check if we are a user -OCP\User::checkLoggedIn(); - $config = \OC::$server->getConfig(); // TODO: move this to the generated config.js $publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php index e2c70062bf39f..24cd9cd9aebac 100644 --- a/apps/files_external/settings.php +++ b/apps/files_external/settings.php @@ -26,8 +26,6 @@ use \OCA\Files_External\Service\BackendService; -\OCP\User::checkAdminUser(); - // we must use the same container $appContainer = \OC_Mount_Config::$app->getContainer(); $backendService = $appContainer->query('OCA\Files_External\Service\BackendService'); diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index fb4d983517e9c..5c69b2ed961de 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -27,8 +27,6 @@ * */ -OC_Util::checkAdminUser(); - // fill template $tmpl = new OCP\Template('user_ldap', 'settings'); From fe1089e98a474888fe96f54a9bdf06cadb0f66f6 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 27 Jun 2016 20:36:23 +0200 Subject: [PATCH 30/81] Add tooltip --- apps/theming/js/settings-admin.js | 1 + apps/theming/templates/settings-admin.php | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 86c22471adbcd..916e1ec32e9e2 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -52,6 +52,7 @@ function preview(setting, value) { } $(document).ready(function () { + $('#theming [data-toggle="tooltip"]').tooltip(); var uploadParamsLogo = { pasteZone: null, diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index f802b947c8008..27cdd8b60a3d4 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -17,32 +17,32 @@ - +

- +

- +

- +

- +

@@ -50,7 +50,7 @@ - +

From 4b7942047d98684c843ec0b8ae62d2b7d0d93581 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 27 Jun 2016 20:46:12 +0200 Subject: [PATCH 31/81] Only save when value changed or enter is pressed --- apps/theming/js/settings-admin.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 916e1ec32e9e2..bd4b4b34ed1df 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -86,28 +86,34 @@ $(document).ready(function () { $('#uploadlogo').fileupload(uploadParamsLogo); $('#upload-login-background').fileupload(uploadParamsLogin); - $('#theming-name').keyup(function (e) { + $('#theming-name').change(function(e) { + var el = $(this); + $.when(el.focusout()).then(function() { + setThemingValue('name', $(this).val()); + }); if (e.keyCode == 13) { setThemingValue('name', $(this).val()); } - }).focusout(function (e) { - setThemingValue('name', $(this).val()); }); - $('#theming-url').keyup(function (e) { + $('#theming-url').change(function(e) { + var el = $(this); + $.when(el.focusout()).then(function() { + setThemingValue('url', $(this).val()); + }); if (e.keyCode == 13) { setThemingValue('url', $(this).val()); } - }).focusout(function (e) { - setThemingValue('url', $(this).val()); }); - $('#theming-slogan').keyup(function (e) { + $('#theming-slogan').change(function(e) { + var el = $(this); + $.when(el.focusout()).then(function() { + setThemingValue('slogan', $(this).val()); + }); if (e.keyCode == 13) { setThemingValue('slogan', $(this).val()); } - }).focusout(function (e) { - setThemingValue('slogan', $(this).val()); }); $('#theming-color').change(function (e) { From f107be3d295d5a7cae7bc43559396b56030fc57c Mon Sep 17 00:00:00 2001 From: Georg Ehrke Date: Mon, 27 Jun 2016 21:26:56 +0200 Subject: [PATCH 32/81] fix a ImageExportPlugin Test (#25215) --- apps/dav/lib/CardDAV/ImageExportPlugin.php | 14 ++++++++++++-- .../tests/unit/CardDAV/ImageExportPluginTest.php | 9 +++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/dav/lib/CardDAV/ImageExportPlugin.php b/apps/dav/lib/CardDAV/ImageExportPlugin.php index 3f505222491f4..fcd36b3ff35a3 100644 --- a/apps/dav/lib/CardDAV/ImageExportPlugin.php +++ b/apps/dav/lib/CardDAV/ImageExportPlugin.php @@ -108,8 +108,18 @@ function getPhoto(Card $node) { $photo = $vObject->PHOTO; $type = $this->getType($photo); - $valType = $photo->getValueType(); - $val = ($valType === 'URI' ? $photo->getRawMimeDirValue() : $photo->getValue()); + $val = $photo->getValue(); + if ($photo->getValueType() === 'URI') { + $parsed = \Sabre\URI\parse($val); + //only allow data:// + if ($parsed['scheme'] !== 'data') { + return false; + } + if (substr_count($parsed['path'], ';') === 1) { + list($type,) = explode(';', $parsed['path']); + } + $val = file_get_contents($val); + } return [ 'Content-Type' => $type, 'body' => $val diff --git a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php index 8583df0b6f919..3a9dc144584b4 100644 --- a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php +++ b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php @@ -140,12 +140,9 @@ public function providesPhotoData() { 'empty vcard' => [false, ''], 'vcard without PHOTO' => [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n"], 'vcard 3 with PHOTO' => [['Content-Type' => 'image/jpeg', 'body' => '12345'], "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU=\r\nEND:VCARD\r\n"], - // - // TODO: these three below are not working - needs debugging - // - //'vcard 3 with PHOTO URL' => [['Content-Type' => 'image/jpeg', 'body' => '12345'], "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;TYPE=JPEG:http://example.org/photo.jpg\r\nEND:VCARD\r\n"], - //'vcard 4 with PHOTO' => [['Content-Type' => 'image/jpeg', 'body' => '12345'], "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO:data:image/jpeg;MTIzNDU=\r\nEND:VCARD\r\n"], - 'vcard 4 with PHOTO URL' => [['Content-Type' => 'image/jpeg', 'body' => 'http://example.org/photo.jpg'], "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;MEDIATYPE=image/jpeg:http://example.org/photo.jpg\r\nEND:VCARD\r\n"], + 'vcard 3 with PHOTO URL' => [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;TYPE=JPEG;VALUE=URI:http://example.com/photo.jpg\r\nEND:VCARD\r\n"], + 'vcard 4 with PHOTO' => [['Content-Type' => 'image/jpeg', 'body' => '12345'], "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO:data:image/jpeg;base64,MTIzNDU=\r\nEND:VCARD\r\n"], + 'vcard 4 with PHOTO URL' => [false, "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;MEDIATYPE=image/jpeg:http://example.org/photo.jpg\r\nEND:VCARD\r\n"], ]; } } From 332b38fd921f3ce1181a4c1308565b323dd50467 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 27 Jun 2016 21:34:28 +0200 Subject: [PATCH 33/81] handle unavailable fed shares while testing for availability (#25277) * More explicit http status codes * handle unavailable fed shares while testing for availability --- apps/files_sharing/lib/External/Storage.php | 19 +++++++++++++++++-- lib/private/Files/Storage/DAV.php | 6 +++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php index 29b9c7b563cac..bc8d898f8ef37 100644 --- a/apps/files_sharing/lib/External/Storage.php +++ b/apps/files_sharing/lib/External/Storage.php @@ -32,6 +32,7 @@ use OC\ForbiddenException; use OCA\FederatedFileSharing\DiscoveryManager; use OCA\Files_Sharing\ISharedStorage; +use OCP\AppFramework\Http; use OCP\Files\NotFoundException; use OCP\Files\StorageInvalidException; use OCP\Files\StorageNotAvailableException; @@ -181,6 +182,20 @@ public function hasUpdated($path, $time) { } } + public function test() { + try { + parent::test(); + } catch (StorageInvalidException $e) { + // check if it needs to be removed + $this->checkStorageAvailability(); + throw $e; + } catch (StorageNotAvailableException $e) { + // check if it needs to be removed or just temp unavailable + $this->checkStorageAvailability(); + throw $e; + } + } + /** * Check whether this storage is permanently or temporarily * unavailable @@ -310,10 +325,10 @@ public function getShareInfo() { 'connect_timeout' => 10, ]); } catch (\GuzzleHttp\Exception\RequestException $e) { - if ($e->getCode() === 401 || $e->getCode() === 403) { + if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) { throw new ForbiddenException(); } - if ($e->getCode() === 404) { + if ($e->getCode() === Http::STATUS_NOT_FOUND) { throw new NotFoundException(); } // throw this to be on the safe side: the share will still be visible diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index 0d41b3bab029f..c8088a41c47ce 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -814,13 +814,13 @@ public function hasUpdated($path, $time) { private function convertException(Exception $e, $path = '') { Util::writeLog('files_external', $e->getMessage(), Util::ERROR); if ($e instanceof ClientHttpException) { - if ($e->getHttpStatus() === 423) { + if ($e->getHttpStatus() === Http::STATUS_LOCKED) { throw new \OCP\Lock\LockedException($path); } - if ($e->getHttpStatus() === 401) { + if ($e->getHttpStatus() === Http::STATUS_UNAUTHORIZED) { // either password was changed or was invalid all along throw new StorageInvalidException(get_class($e) . ': ' . $e->getMessage()); - } else if ($e->getHttpStatus() === 405) { + } else if ($e->getHttpStatus() === Http::STATUS_METHOD_NOT_ALLOWED) { // ignore exception for MethodNotAllowed, false will be returned return; } From 86a0e6462898d1f8b3c2359edc728ee49f246cda Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Mon, 27 Jun 2016 22:16:22 +0200 Subject: [PATCH 34/81] Login hooks (#25260) * fix login hooks * adjust user session tests * fix login return value of successful token logins * trigger preLogin hook earlier; extract method 'loginWithPassword' * call postLogin hook earlier; add PHPDoc --- lib/private/User/Session.php | 101 ++++++++++++++++++++------------- tests/lib/User/SessionTest.php | 5 +- 2 files changed, 65 insertions(+), 41 deletions(-) diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 6219a89e5b3b0..dcc2e66c6c382 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -280,46 +280,11 @@ public function getLoginName() { */ public function login($uid, $password) { $this->session->regenerateId(); - if ($this->validateToken($password, $uid)) { - // When logging in with token, the password must be decrypted first before passing to login hook - try { - $token = $this->tokenProvider->getToken($password); - try { - $loginPassword = $this->tokenProvider->getPassword($token, $password); - $this->manager->emit('\OC\User', 'preLogin', array($uid, $loginPassword)); - } catch (PasswordlessTokenException $ex) { - $this->manager->emit('\OC\User', 'preLogin', array($uid, '')); - } - } catch (InvalidTokenException $ex) { - // Invalid token, nothing to do - } - $this->loginWithToken($password); - $user = $this->getUser(); + if ($this->validateToken($password, $uid)) { + return $this->loginWithToken($password); } else { - $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); - $user = $this->manager->checkPassword($uid, $password); - } - if ($user !== false) { - if (!is_null($user)) { - if ($user->isEnabled()) { - $this->setUser($user); - $this->setLoginName($uid); - $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); - if ($this->isLoggedIn()) { - $this->prepareUserLogin(); - return true; - } else { - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); - throw new LoginException($message); - } - } else { - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('User disabled'); - throw new LoginException($message); - } - } + return $this->loginWithPassword($uid, $password); } return false; } @@ -449,6 +414,49 @@ public function tryBasicAuthLogin(IRequest $request) { return false; } + /** + * Log an user in via login name and password + * + * @param string $uid + * @param string $password + * @return boolean + * @throws LoginException if an app canceld the login process or the user is not enabled + */ + private function loginWithPassword($uid, $password) { + $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); + $user = $this->manager->checkPassword($uid, $password); + if ($user === false) { + // Password check failed + return false; + } + + if ($user->isEnabled()) { + $this->setUser($user); + $this->setLoginName($uid); + $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); + if ($this->isLoggedIn()) { + $this->prepareUserLogin(); + return true; + } else { + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); + throw new LoginException($message); + } + } else { + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('User disabled'); + throw new LoginException($message); + } + return false; + } + + /** + * Log an user in with a given token (id) + * + * @param string $token + * @return boolean + * @throws LoginException if an app canceld the login process or the user is not enabled + */ private function loginWithToken($token) { try { $dbToken = $this->tokenProvider->getToken($token); @@ -457,12 +465,14 @@ private function loginWithToken($token) { } $uid = $dbToken->getUID(); + // When logging in with token, the password must be decrypted first before passing to login hook $password = ''; try { $password = $this->tokenProvider->getPassword($dbToken, $token); } catch (PasswordlessTokenException $ex) { // Ignore and use empty string instead } + $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); $user = $this->manager->get($uid); @@ -472,13 +482,24 @@ private function loginWithToken($token) { } if (!$user->isEnabled()) { // disabled users can not log in - return false; + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('User disabled'); + throw new LoginException($message); } //login $this->setUser($user); - + $this->setLoginName($dbToken->getLoginName()); $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); + + if ($this->isLoggedIn()) { + $this->prepareUserLogin(); + } else { + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); + throw new LoginException($message); + } + return true; } diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php index 447c6142f3414..9bde2c664b601 100644 --- a/tests/lib/User/SessionTest.php +++ b/tests/lib/User/SessionTest.php @@ -729,6 +729,9 @@ public function testCreateSessionTokenWithNonExistentUser() { $this->assertFalse($userSession->createSessionToken($request, $uid, $loginName, $password)); } + /** + * @expectedException \OC\User\LoginException + */ public function testTryTokenLoginWithDisabledUser() { $manager = $this->getMockBuilder('\OC\User\Manager') ->disableOriginalConstructor() @@ -761,7 +764,7 @@ public function testTryTokenLoginWithDisabledUser() { ->method('isEnabled') ->will($this->returnValue(false)); - $this->assertFalse($userSession->tryTokenLogin($request)); + $userSession->tryTokenLogin($request); } public function testValidateSessionDisabledUser() { From b40013928cf155116f1703adf434d8728529e3ee Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 27 Jun 2016 22:26:43 +0200 Subject: [PATCH 35/81] Fix getting the certificate bundle for dav external storage (#25274) * Fix getting the certificate bundle for dav external storages * Log the original exception in dav external storage --- apps/files_sharing/lib/External/Manager.php | 2 +- lib/private/Files/Storage/DAV.php | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php index e338e6e509cea..3f665b0978d58 100644 --- a/apps/files_sharing/lib/External/Manager.php +++ b/apps/files_sharing/lib/External/Manager.php @@ -328,7 +328,7 @@ public function setMountPoint($source, $target) { public function removeShare($mountPoint) { $mountPointObj = $this->mountManager->find($mountPoint); - $id = $mountPointObj->getStorage()->getCache()->getId(); + $id = $mountPointObj->getStorage()->getCache()->getId(''); $mountPoint = $this->stripPath($mountPoint); $hash = md5($mountPoint); diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index c8088a41c47ce..7eb6aa199b147 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -107,7 +107,11 @@ public function __construct($params) { } if ($this->secure === true) { // inject mock for testing - $certPath = \OC_User::getHome(\OC_User::getUser()) . '/files_external/rootcerts.crt'; + $certManager = \OC::$server->getCertificateManager(); + if (is_null($certManager)) { //no user + $certManager = \OC::$server->getCertificateManager(null); + } + $certPath = $certManager->getAbsoluteBundlePath(); if (file_exists($certPath)) { $this->certPath = $certPath; } @@ -812,6 +816,7 @@ public function hasUpdated($path, $time) { * which might be temporary */ private function convertException(Exception $e, $path = '') { + \OC::$server->getLogger()->logException($e); Util::writeLog('files_external', $e->getMessage(), Util::ERROR); if ($e instanceof ClientHttpException) { if ($e->getHttpStatus() === Http::STATUS_LOCKED) { From a8ccc71df58ad6de797aa0d45b00fe16bd5eb1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Bl=C3=BCm?= Date: Mon, 27 Jun 2016 23:18:01 +0200 Subject: [PATCH 36/81] Get rid of LGTM self approvals * add missing spaces --- .lgtm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.lgtm b/.lgtm index 5625d21b1dc2a..612c35f520edb 100644 --- a/.lgtm +++ b/.lgtm @@ -1,2 +1,2 @@ pattern = "(?i):shipit:|:\\+1:|LGTM|👍" -self_approval_off=true +self_approval_off = true From 20b1ba07716a13374f0f9627d230a282bda5f9d9 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Tue, 28 Jun 2016 01:57:10 -0400 Subject: [PATCH 37/81] [tx-robot] updated from transifex --- apps/comments/l10n/en_GB.js | 3 + apps/comments/l10n/en_GB.json | 3 + apps/comments/l10n/fr.js | 3 + apps/comments/l10n/fr.json | 3 + apps/comments/l10n/pt_BR.js | 3 + apps/comments/l10n/pt_BR.json | 3 + apps/comments/l10n/ru.js | 3 + apps/comments/l10n/ru.json | 3 + apps/federatedfilesharing/l10n/fr.js | 2 + apps/federatedfilesharing/l10n/fr.json | 2 + apps/federation/l10n/lb.js | 15 ++ apps/federation/l10n/lb.json | 13 ++ apps/files/l10n/lb.js | 4 + apps/files/l10n/lb.json | 4 + apps/files_external/l10n/lb.js | 3 + apps/files_external/l10n/lb.json | 3 + apps/systemtags/l10n/lb.js | 22 +++ apps/systemtags/l10n/lb.json | 22 +++ apps/updatenotification/l10n/fr.js | 4 +- apps/updatenotification/l10n/fr.json | 4 +- core/l10n/lb.js | 12 ++ core/l10n/lb.json | 12 ++ lib/l10n/lb.js | 2 + lib/l10n/lb.json | 2 + settings/l10n/ar.js | 2 +- settings/l10n/ar.json | 2 +- settings/l10n/ast.js | 2 +- settings/l10n/ast.json | 2 +- settings/l10n/az.js | 2 +- settings/l10n/az.json | 2 +- settings/l10n/bg_BG.js | 2 +- settings/l10n/bg_BG.json | 2 +- settings/l10n/bn_BD.js | 2 +- settings/l10n/bn_BD.json | 2 +- settings/l10n/bn_IN.js | 4 +- settings/l10n/bn_IN.json | 4 +- settings/l10n/bs.js | 2 +- settings/l10n/bs.json | 2 +- settings/l10n/ca.js | 2 +- settings/l10n/ca.json | 2 +- settings/l10n/cs_CZ.js | 2 +- settings/l10n/cs_CZ.json | 2 +- settings/l10n/da.js | 2 +- settings/l10n/da.json | 2 +- settings/l10n/de.js | 2 +- settings/l10n/de.json | 2 +- settings/l10n/de_DE.js | 2 +- settings/l10n/de_DE.json | 2 +- settings/l10n/el.js | 2 +- settings/l10n/el.json | 2 +- settings/l10n/en_GB.js | 2 +- settings/l10n/en_GB.json | 2 +- settings/l10n/eo.js | 2 +- settings/l10n/eo.json | 2 +- settings/l10n/es.js | 2 +- settings/l10n/es.json | 2 +- settings/l10n/es_AR.js | 2 +- settings/l10n/es_AR.json | 2 +- settings/l10n/es_MX.js | 2 +- settings/l10n/es_MX.json | 2 +- settings/l10n/et_EE.js | 2 +- settings/l10n/et_EE.json | 2 +- settings/l10n/eu.js | 2 +- settings/l10n/eu.json | 2 +- settings/l10n/fa.js | 2 +- settings/l10n/fa.json | 2 +- settings/l10n/fi_FI.js | 2 +- settings/l10n/fi_FI.json | 2 +- settings/l10n/fr.js | 2 +- settings/l10n/fr.json | 2 +- settings/l10n/gl.js | 2 +- settings/l10n/gl.json | 2 +- settings/l10n/he.js | 2 +- settings/l10n/he.json | 2 +- settings/l10n/hr.js | 2 +- settings/l10n/hr.json | 2 +- settings/l10n/hu_HU.js | 2 +- settings/l10n/hu_HU.json | 2 +- settings/l10n/ia.js | 2 +- settings/l10n/ia.json | 2 +- settings/l10n/id.js | 2 +- settings/l10n/id.json | 2 +- settings/l10n/is.js | 2 +- settings/l10n/is.json | 2 +- settings/l10n/it.js | 2 +- settings/l10n/it.json | 2 +- settings/l10n/ja.js | 2 +- settings/l10n/ja.json | 2 +- settings/l10n/ka_GE.js | 2 +- settings/l10n/ka_GE.json | 2 +- settings/l10n/km.js | 2 +- settings/l10n/km.json | 2 +- settings/l10n/ko.js | 2 +- settings/l10n/ko.json | 2 +- settings/l10n/lb.js | 211 ++++++++++++++++++++++++- settings/l10n/lb.json | 211 ++++++++++++++++++++++++- settings/l10n/lt_LT.js | 2 +- settings/l10n/lt_LT.json | 2 +- settings/l10n/lv.js | 2 +- settings/l10n/lv.json | 2 +- settings/l10n/mk.js | 2 +- settings/l10n/mk.json | 2 +- settings/l10n/mn.js | 4 +- settings/l10n/mn.json | 4 +- settings/l10n/nb_NO.js | 2 +- settings/l10n/nb_NO.json | 2 +- settings/l10n/nl.js | 2 +- settings/l10n/nl.json | 2 +- settings/l10n/nn_NO.js | 2 +- settings/l10n/nn_NO.json | 2 +- settings/l10n/oc.js | 2 +- settings/l10n/oc.json | 2 +- settings/l10n/pl.js | 2 +- settings/l10n/pl.json | 2 +- settings/l10n/pt_BR.js | 2 +- settings/l10n/pt_BR.json | 2 +- settings/l10n/pt_PT.js | 2 +- settings/l10n/pt_PT.json | 2 +- settings/l10n/ro.js | 2 +- settings/l10n/ro.json | 2 +- settings/l10n/ru.js | 2 +- settings/l10n/ru.json | 2 +- settings/l10n/sk_SK.js | 2 +- settings/l10n/sk_SK.json | 2 +- settings/l10n/sl.js | 2 +- settings/l10n/sl.json | 2 +- settings/l10n/sq.js | 2 +- settings/l10n/sq.json | 2 +- settings/l10n/sr.js | 2 +- settings/l10n/sr.json | 2 +- settings/l10n/sr@latin.js | 2 +- settings/l10n/sr@latin.json | 2 +- settings/l10n/sv.js | 2 +- settings/l10n/sv.json | 2 +- settings/l10n/th_TH.js | 2 +- settings/l10n/th_TH.json | 2 +- settings/l10n/tr.js | 2 +- settings/l10n/tr.json | 2 +- settings/l10n/uk.js | 2 +- settings/l10n/uk.json | 2 +- settings/l10n/vi.js | 2 +- settings/l10n/vi.json | 2 +- settings/l10n/zh_CN.js | 2 +- settings/l10n/zh_CN.json | 2 +- settings/l10n/zh_HK.js | 2 +- settings/l10n/zh_HK.json | 2 +- settings/l10n/zh_TW.js | 2 +- settings/l10n/zh_TW.json | 2 +- 148 files changed, 686 insertions(+), 138 deletions(-) create mode 100644 apps/federation/l10n/lb.js create mode 100644 apps/federation/l10n/lb.json diff --git a/apps/comments/l10n/en_GB.js b/apps/comments/l10n/en_GB.js index d8e5c5d824059..057ac775a6bce 100644 --- a/apps/comments/l10n/en_GB.js +++ b/apps/comments/l10n/en_GB.js @@ -12,6 +12,9 @@ OC.L10N.register( "More comments..." : "More comments...", "Save" : "Save", "Allowed characters {count} of {max}" : "Allowed characters {count} of {max}", + "Error occurred while retrieving comment with id {id}" : "Error occurred while retrieving comment with id {id}", + "Error occurred while updating comment with id {id}" : "Error occurred while updating comment with id {id}", + "Error occurred while posting comment" : "Error occurred while posting comment", "{count} unread comments" : "{count} unread comments", "Comment" : "Comment", "Comments for files (always listed in stream)" : "Comments for files (always listed in stream)", diff --git a/apps/comments/l10n/en_GB.json b/apps/comments/l10n/en_GB.json index ccf4a1338d197..13335d5d98919 100644 --- a/apps/comments/l10n/en_GB.json +++ b/apps/comments/l10n/en_GB.json @@ -10,6 +10,9 @@ "More comments..." : "More comments...", "Save" : "Save", "Allowed characters {count} of {max}" : "Allowed characters {count} of {max}", + "Error occurred while retrieving comment with id {id}" : "Error occurred while retrieving comment with id {id}", + "Error occurred while updating comment with id {id}" : "Error occurred while updating comment with id {id}", + "Error occurred while posting comment" : "Error occurred while posting comment", "{count} unread comments" : "{count} unread comments", "Comment" : "Comment", "Comments for files (always listed in stream)" : "Comments for files (always listed in stream)", diff --git a/apps/comments/l10n/fr.js b/apps/comments/l10n/fr.js index 720c9518b2e60..adb5bc00c1c87 100644 --- a/apps/comments/l10n/fr.js +++ b/apps/comments/l10n/fr.js @@ -12,6 +12,9 @@ OC.L10N.register( "More comments..." : "Plus de commentaires...", "Save" : "Enregistrer", "Allowed characters {count} of {max}" : "{count} sur {max} caractères autorisés", + "Error occurred while retrieving comment with id {id}" : "Une erreur est survenue lors de la récupération du commentaire avec l'id {id}", + "Error occurred while updating comment with id {id}" : "Une erreur est survenue lors de la mise à jour du commentaire avec l'id {id}", + "Error occurred while posting comment" : "Une erreur est survenue lors de l'envoi du commentaire", "{count} unread comments" : "{count} commentaires non lus", "Comment" : "Commenter", "Comments for files (always listed in stream)" : "Commentaires pour les fichiers (toujours listés dans le flux)", diff --git a/apps/comments/l10n/fr.json b/apps/comments/l10n/fr.json index 25cbfa4daa2cc..9a7dce480c80e 100644 --- a/apps/comments/l10n/fr.json +++ b/apps/comments/l10n/fr.json @@ -10,6 +10,9 @@ "More comments..." : "Plus de commentaires...", "Save" : "Enregistrer", "Allowed characters {count} of {max}" : "{count} sur {max} caractères autorisés", + "Error occurred while retrieving comment with id {id}" : "Une erreur est survenue lors de la récupération du commentaire avec l'id {id}", + "Error occurred while updating comment with id {id}" : "Une erreur est survenue lors de la mise à jour du commentaire avec l'id {id}", + "Error occurred while posting comment" : "Une erreur est survenue lors de l'envoi du commentaire", "{count} unread comments" : "{count} commentaires non lus", "Comment" : "Commenter", "Comments for files (always listed in stream)" : "Commentaires pour les fichiers (toujours listés dans le flux)", diff --git a/apps/comments/l10n/pt_BR.js b/apps/comments/l10n/pt_BR.js index 173fc5395fb33..a366f3bcda17a 100644 --- a/apps/comments/l10n/pt_BR.js +++ b/apps/comments/l10n/pt_BR.js @@ -12,6 +12,9 @@ OC.L10N.register( "More comments..." : "Mais comentários...", "Save" : "Salvar", "Allowed characters {count} of {max}" : "Caracteres permitidos {count} de {max}", + "Error occurred while retrieving comment with id {id}" : "Ocorreu um erro ao recuperar comentário com o id {id}", + "Error occurred while updating comment with id {id}" : "Ocorreu um erro durante a atualização do comentário com o id {id}", + "Error occurred while posting comment" : "Ocorreu um erro ao postar o comentário", "{count} unread comments" : "{count} comentários não lidos", "Comment" : "Comentário", "Comments for files (always listed in stream)" : "Comemtários para arquivos (sempre listados no fluxo)", diff --git a/apps/comments/l10n/pt_BR.json b/apps/comments/l10n/pt_BR.json index b20ea2620b137..11fa6bc3f6826 100644 --- a/apps/comments/l10n/pt_BR.json +++ b/apps/comments/l10n/pt_BR.json @@ -10,6 +10,9 @@ "More comments..." : "Mais comentários...", "Save" : "Salvar", "Allowed characters {count} of {max}" : "Caracteres permitidos {count} de {max}", + "Error occurred while retrieving comment with id {id}" : "Ocorreu um erro ao recuperar comentário com o id {id}", + "Error occurred while updating comment with id {id}" : "Ocorreu um erro durante a atualização do comentário com o id {id}", + "Error occurred while posting comment" : "Ocorreu um erro ao postar o comentário", "{count} unread comments" : "{count} comentários não lidos", "Comment" : "Comentário", "Comments for files (always listed in stream)" : "Comemtários para arquivos (sempre listados no fluxo)", diff --git a/apps/comments/l10n/ru.js b/apps/comments/l10n/ru.js index 3ee5e1fb4d4b1..c7719d185e808 100644 --- a/apps/comments/l10n/ru.js +++ b/apps/comments/l10n/ru.js @@ -12,6 +12,9 @@ OC.L10N.register( "More comments..." : "Ещё комментарии...", "Save" : "Сохранить", "Allowed characters {count} of {max}" : "Допустимых символов {count} из {max}", + "Error occurred while retrieving comment with id {id}" : "Произошла ошибка при извлечении комментария с id {id}", + "Error occurred while updating comment with id {id}" : "Произошла ошибка при обновлении комментария с id {id}", + "Error occurred while posting comment" : "При сохранении комментария произошла ошибка", "{count} unread comments" : "{count} непрочитанных комментариев", "Comment" : "Коментарий", "Comments for files (always listed in stream)" : "Комментарии к файлам (всегда перечислены в потоке)", diff --git a/apps/comments/l10n/ru.json b/apps/comments/l10n/ru.json index fcafda4c9cb8b..3de3e3d8ecd0b 100644 --- a/apps/comments/l10n/ru.json +++ b/apps/comments/l10n/ru.json @@ -10,6 +10,9 @@ "More comments..." : "Ещё комментарии...", "Save" : "Сохранить", "Allowed characters {count} of {max}" : "Допустимых символов {count} из {max}", + "Error occurred while retrieving comment with id {id}" : "Произошла ошибка при извлечении комментария с id {id}", + "Error occurred while updating comment with id {id}" : "Произошла ошибка при обновлении комментария с id {id}", + "Error occurred while posting comment" : "При сохранении комментария произошла ошибка", "{count} unread comments" : "{count} непрочитанных комментариев", "Comment" : "Коментарий", "Comments for files (always listed in stream)" : "Комментарии к файлам (всегда перечислены в потоке)", diff --git a/apps/federatedfilesharing/l10n/fr.js b/apps/federatedfilesharing/l10n/fr.js index 33a1225e8947b..fc73fe5992caa 100644 --- a/apps/federatedfilesharing/l10n/fr.js +++ b/apps/federatedfilesharing/l10n/fr.js @@ -7,6 +7,8 @@ OC.L10N.register( "Not allowed to create a federated share with the same user" : "Non autorisé à créer un partage fédéré avec le même utilisateur", "File is already shared with %s" : "Le fichier est déjà partagé avec %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Le partage de %s a échoué : impossible de trouver %s. Peut-être le serveur est-il momentanément injoignable.", + "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Vous recevez \"/%3$s\" comme un partage distant depuis %1$s (au nom de %2$s)", + "You received \"/%3$s\" as a remote share from %1$s" : "Vous recevez \"/%3$s\" comme un partage distant depuis %1$s", "Accept" : "Accepter", "Decline" : "Refuser", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Partagez avec moi grâce à mon identifiant Federated Cloud #owncloud %s", diff --git a/apps/federatedfilesharing/l10n/fr.json b/apps/federatedfilesharing/l10n/fr.json index 3944f33f03324..748125645d236 100644 --- a/apps/federatedfilesharing/l10n/fr.json +++ b/apps/federatedfilesharing/l10n/fr.json @@ -5,6 +5,8 @@ "Not allowed to create a federated share with the same user" : "Non autorisé à créer un partage fédéré avec le même utilisateur", "File is already shared with %s" : "Le fichier est déjà partagé avec %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Le partage de %s a échoué : impossible de trouver %s. Peut-être le serveur est-il momentanément injoignable.", + "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Vous recevez \"/%3$s\" comme un partage distant depuis %1$s (au nom de %2$s)", + "You received \"/%3$s\" as a remote share from %1$s" : "Vous recevez \"/%3$s\" comme un partage distant depuis %1$s", "Accept" : "Accepter", "Decline" : "Refuser", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Partagez avec moi grâce à mon identifiant Federated Cloud #owncloud %s", diff --git a/apps/federation/l10n/lb.js b/apps/federation/l10n/lb.js new file mode 100644 index 0000000000000..df0f6d5d07af8 --- /dev/null +++ b/apps/federation/l10n/lb.js @@ -0,0 +1,15 @@ +OC.L10N.register( + "federation", + { + "Server added to the list of trusted ownClouds" : "De Server gouf op d'Lëscht vun den zouverlässegen ownClouds gesat.", + "Server is already in the list of trusted servers." : "De Server ass schonn op der Lëscht vun den zouverlässegen Serveren.", + "No ownCloud server found" : "Keen ownCloud Server fonnt", + "Could not add server" : "De Server konnt net derbäi gesat ginn", + "Federation" : "Federatioun", + "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "D'ownCloud Federatioun erlaabt der fir dech mat aneren zouverlässegen ownClouds ze verbannen an d'Benotzer Verzeechnes auszetauschen. Zum Beispill gëtt dëst hei benotzt fir extern Benotzer automatesch fir federatiivt Deelen ze vervollstännegen.", + "Add server automatically once a federated share was created successfully" : "Setz de Server automatesch derbäi soubal e federativen Undeel erfollegräich erstallt gouf", + "Trusted ownCloud Servers" : "Zouverlässeg ownCloud Serveren", + "+ Add ownCloud server" : "+ ownCloud Server derbäi setzen", + "ownCloud Server" : "ownCloud Server" +}, +"nplurals=2; plural=(n != 1);"); diff --git a/apps/federation/l10n/lb.json b/apps/federation/l10n/lb.json new file mode 100644 index 0000000000000..03179a4b8eeae --- /dev/null +++ b/apps/federation/l10n/lb.json @@ -0,0 +1,13 @@ +{ "translations": { + "Server added to the list of trusted ownClouds" : "De Server gouf op d'Lëscht vun den zouverlässegen ownClouds gesat.", + "Server is already in the list of trusted servers." : "De Server ass schonn op der Lëscht vun den zouverlässegen Serveren.", + "No ownCloud server found" : "Keen ownCloud Server fonnt", + "Could not add server" : "De Server konnt net derbäi gesat ginn", + "Federation" : "Federatioun", + "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "D'ownCloud Federatioun erlaabt der fir dech mat aneren zouverlässegen ownClouds ze verbannen an d'Benotzer Verzeechnes auszetauschen. Zum Beispill gëtt dëst hei benotzt fir extern Benotzer automatesch fir federatiivt Deelen ze vervollstännegen.", + "Add server automatically once a federated share was created successfully" : "Setz de Server automatesch derbäi soubal e federativen Undeel erfollegräich erstallt gouf", + "Trusted ownCloud Servers" : "Zouverlässeg ownCloud Serveren", + "+ Add ownCloud server" : "+ ownCloud Server derbäi setzen", + "ownCloud Server" : "ownCloud Server" +},"pluralForm" :"nplurals=2; plural=(n != 1);" +} \ No newline at end of file diff --git a/apps/files/l10n/lb.js b/apps/files/l10n/lb.js index d7888f9f197ca..9fa3a0fdfaa07 100644 --- a/apps/files/l10n/lb.js +++ b/apps/files/l10n/lb.js @@ -29,14 +29,18 @@ OC.L10N.register( "Size" : "Gréisst", "Modified" : "Geännert", "New" : "Nei", + "\"{name}\" is an invalid file name." : "\"{Numm}\" ass een ongültegen Numm fir e Fichier.", + "File name cannot be empty." : "Den Numm vum Fichier kann net eidel sinn.", "Folder" : "Dossier", "New folder" : "Neien Dossier", "Upload" : "Eroplueden", + "Upload (max. %s)" : "Eroplueden (max. %s)", "File handling" : "Fichier handling", "Maximum upload size" : "Maximum Upload Gréisst ", "max. possible: " : "max. méiglech:", "Save" : "Späicheren", "Settings" : "Astellungen", + "No files in here" : "Hei sinn keng Fichieren", "No entries found in this folder" : "Keng Elementer an dësem Dossier fonnt", "Select all" : "All auswielen", "Upload too large" : "Upload ze grouss", diff --git a/apps/files/l10n/lb.json b/apps/files/l10n/lb.json index a736e06570bc1..67da26b1ece01 100644 --- a/apps/files/l10n/lb.json +++ b/apps/files/l10n/lb.json @@ -27,14 +27,18 @@ "Size" : "Gréisst", "Modified" : "Geännert", "New" : "Nei", + "\"{name}\" is an invalid file name." : "\"{Numm}\" ass een ongültegen Numm fir e Fichier.", + "File name cannot be empty." : "Den Numm vum Fichier kann net eidel sinn.", "Folder" : "Dossier", "New folder" : "Neien Dossier", "Upload" : "Eroplueden", + "Upload (max. %s)" : "Eroplueden (max. %s)", "File handling" : "Fichier handling", "Maximum upload size" : "Maximum Upload Gréisst ", "max. possible: " : "max. méiglech:", "Save" : "Späicheren", "Settings" : "Astellungen", + "No files in here" : "Hei sinn keng Fichieren", "No entries found in this folder" : "Keng Elementer an dësem Dossier fonnt", "Select all" : "All auswielen", "Upload too large" : "Upload ze grouss", diff --git a/apps/files_external/l10n/lb.js b/apps/files_external/l10n/lb.js index 50bb06ff7f9ee..29014e551906c 100644 --- a/apps/files_external/l10n/lb.js +++ b/apps/files_external/l10n/lb.js @@ -15,7 +15,10 @@ OC.L10N.register( "ownCloud" : "ownCloud", "Share" : "Deelen", "Name" : "Numm", + "Enable encryption" : "Verschlësselung aschalten", + "External Storage" : "Externt Lager", "Folder name" : "Dossiers Numm:", + "Advanced settings" : "Erweidert Astellungen", "Delete" : "Läschen" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/lb.json b/apps/files_external/l10n/lb.json index 9f7aa84bb1a1e..ef3f3d2f333bf 100644 --- a/apps/files_external/l10n/lb.json +++ b/apps/files_external/l10n/lb.json @@ -13,7 +13,10 @@ "ownCloud" : "ownCloud", "Share" : "Deelen", "Name" : "Numm", + "Enable encryption" : "Verschlësselung aschalten", + "External Storage" : "Externt Lager", "Folder name" : "Dossiers Numm:", + "Advanced settings" : "Erweidert Astellungen", "Delete" : "Läschen" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/systemtags/l10n/lb.js b/apps/systemtags/l10n/lb.js index aa83421b4f174..6af879ce2f418 100644 --- a/apps/systemtags/l10n/lb.js +++ b/apps/systemtags/l10n/lb.js @@ -2,6 +2,28 @@ OC.L10N.register( "systemtags", { "Tags" : "Etiketten", + "Tagged files" : "Etikettéiert Fichieren", + "Select tags to filter by" : "Wiel d'Etiketten fir ze siften aus", + "Please select tags to filter by" : "Wiel w.e.g. d'Etiketten fir ze siften aus", + "No files found for the selected tags" : "Keng Fichieren fir d'ausgewielten Etiketten fonnt", + "System tags for a file have been modified" : "System Etiketten fir e Fichier goufen verännert", + "You assigned system tag %3$s" : "Du hues d'System Etikett %3$s zougewisen ", + "%1$s assigned system tag %3$s" : "%1$s zougewise System Etikett %3$s", + "You unassigned system tag %3$s" : "Du hues d'System Etikett %3$s ewechgeholl", + "%1$s unassigned system tag %3$s" : "%1$s System Etikett ewechgeholl %3$s", + "You created system tag %2$s" : "Du hues d'System Etikett %2$s erschafen", + "%1$s created system tag %2$s" : "%1$s System Etikett erschaf %2$s ", + "You deleted system tag %2$s" : "Du hues d'System Etikett %2$s ewechgeholl", + "%1$s deleted system tag %2$s" : "%1$s System Etikett ewechgeholl %2$s", + "You updated system tag %3$s to %2$s" : "Du hues d'System Etikett %3$s op %2$s erneiert", + "%1$s updated system tag %3$s to %2$s" : "%1$s System Etikett erneiert %3$s op %2$s", + "You assigned system tag %3$s to %2$s" : "Du hues d'System Etikett %3$s op %2$s zougewisen", + "%1$s assigned system tag %3$s to %2$s" : "%1$s zougewise System Etikett %3$s op %2$s", + "You unassigned system tag %3$s from %2$s" : "Du hues d'System Etikett %3$s vum %2$s ewechgeholl", + "%1$s unassigned system tag %3$s from %2$s" : "%1$s System Etikett ewechgeholl %3$s vum %2$s", + "%s (restricted)" : "%s (ageschränkt)", + "%s (invisible)" : "%s (onsiichtbar)", + "No files in here" : "Hei sinn keng Fichieren", "No entries found in this folder" : "Keng Elementer an dësem Dossier fonnt", "Name" : "Numm", "Size" : "Gréisst", diff --git a/apps/systemtags/l10n/lb.json b/apps/systemtags/l10n/lb.json index e905615bcd71b..c94e08b607be4 100644 --- a/apps/systemtags/l10n/lb.json +++ b/apps/systemtags/l10n/lb.json @@ -1,5 +1,27 @@ { "translations": { "Tags" : "Etiketten", + "Tagged files" : "Etikettéiert Fichieren", + "Select tags to filter by" : "Wiel d'Etiketten fir ze siften aus", + "Please select tags to filter by" : "Wiel w.e.g. d'Etiketten fir ze siften aus", + "No files found for the selected tags" : "Keng Fichieren fir d'ausgewielten Etiketten fonnt", + "System tags for a file have been modified" : "System Etiketten fir e Fichier goufen verännert", + "You assigned system tag %3$s" : "Du hues d'System Etikett %3$s zougewisen ", + "%1$s assigned system tag %3$s" : "%1$s zougewise System Etikett %3$s", + "You unassigned system tag %3$s" : "Du hues d'System Etikett %3$s ewechgeholl", + "%1$s unassigned system tag %3$s" : "%1$s System Etikett ewechgeholl %3$s", + "You created system tag %2$s" : "Du hues d'System Etikett %2$s erschafen", + "%1$s created system tag %2$s" : "%1$s System Etikett erschaf %2$s ", + "You deleted system tag %2$s" : "Du hues d'System Etikett %2$s ewechgeholl", + "%1$s deleted system tag %2$s" : "%1$s System Etikett ewechgeholl %2$s", + "You updated system tag %3$s to %2$s" : "Du hues d'System Etikett %3$s op %2$s erneiert", + "%1$s updated system tag %3$s to %2$s" : "%1$s System Etikett erneiert %3$s op %2$s", + "You assigned system tag %3$s to %2$s" : "Du hues d'System Etikett %3$s op %2$s zougewisen", + "%1$s assigned system tag %3$s to %2$s" : "%1$s zougewise System Etikett %3$s op %2$s", + "You unassigned system tag %3$s from %2$s" : "Du hues d'System Etikett %3$s vum %2$s ewechgeholl", + "%1$s unassigned system tag %3$s from %2$s" : "%1$s System Etikett ewechgeholl %3$s vum %2$s", + "%s (restricted)" : "%s (ageschränkt)", + "%s (invisible)" : "%s (onsiichtbar)", + "No files in here" : "Hei sinn keng Fichieren", "No entries found in this folder" : "Keng Elementer an dësem Dossier fonnt", "Name" : "Numm", "Size" : "Gréisst", diff --git a/apps/updatenotification/l10n/fr.js b/apps/updatenotification/l10n/fr.js index 6138142770083..afcc041fa514a 100644 --- a/apps/updatenotification/l10n/fr.js +++ b/apps/updatenotification/l10n/fr.js @@ -4,6 +4,7 @@ OC.L10N.register( "Update notifications" : "Notifications de mises à jour", "{version} is available. Get more information on how to update." : "La version {version} est disponible. Cliquez ici pour plus d'informations sur comment mettre à jour.", "Updated channel" : "Canal à jour", + "ownCloud core" : "Base d'ownCloud", "Update for %1$s to version %2$s is available." : "Une mise à jour de %1$s vers la version %2$s est disponible.", "Updater" : "Mises à jour", "A new version is available: %s" : "Une nouvelle version est disponible : %s", @@ -12,6 +13,7 @@ OC.L10N.register( "Checked on %s" : "Vérifié le %s", "Update channel:" : "Canal de mise à jour :", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Vous pouvez à tout moment mettre à jour vers une version plus récente ou un canal expérimental. Cependant vous ne pourrez jamais revenir à un canal plus stable.", - "Notify members of the following groups about available updates:" : "Notifier les membres des groupes suivants des mises à jours disponibles :" + "Notify members of the following groups about available updates:" : "Notifier les membres des groupes suivants des mises à jours disponibles :", + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Seules les notifications pour le mises à jour d'apllication sont disponibles, car le canal de mise à jour sélectionné pour ownCloud ne propose pas lui-même les mises à jour." }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/updatenotification/l10n/fr.json b/apps/updatenotification/l10n/fr.json index 590c3cbb27dd2..0bd2bb57f834c 100644 --- a/apps/updatenotification/l10n/fr.json +++ b/apps/updatenotification/l10n/fr.json @@ -2,6 +2,7 @@ "Update notifications" : "Notifications de mises à jour", "{version} is available. Get more information on how to update." : "La version {version} est disponible. Cliquez ici pour plus d'informations sur comment mettre à jour.", "Updated channel" : "Canal à jour", + "ownCloud core" : "Base d'ownCloud", "Update for %1$s to version %2$s is available." : "Une mise à jour de %1$s vers la version %2$s est disponible.", "Updater" : "Mises à jour", "A new version is available: %s" : "Une nouvelle version est disponible : %s", @@ -10,6 +11,7 @@ "Checked on %s" : "Vérifié le %s", "Update channel:" : "Canal de mise à jour :", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Vous pouvez à tout moment mettre à jour vers une version plus récente ou un canal expérimental. Cependant vous ne pourrez jamais revenir à un canal plus stable.", - "Notify members of the following groups about available updates:" : "Notifier les membres des groupes suivants des mises à jours disponibles :" + "Notify members of the following groups about available updates:" : "Notifier les membres des groupes suivants des mises à jours disponibles :", + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Seules les notifications pour le mises à jour d'apllication sont disponibles, car le canal de mise à jour sélectionné pour ownCloud ne propose pas lui-même les mises à jour." },"pluralForm" :"nplurals=2; plural=(n > 1);" } \ No newline at end of file diff --git a/core/l10n/lb.js b/core/l10n/lb.js index dfd8e7a0f62b8..966b5d289a4d9 100644 --- a/core/l10n/lb.js +++ b/core/l10n/lb.js @@ -60,17 +60,27 @@ OC.L10N.register( "Continue" : "Weider", "(all selected)" : "(all ausgewielt)", "({count} selected)" : "({count} ausgewielt)", + "Very weak password" : "Ganz schwaacht Passwuert", + "Weak password" : "Schwaacht Passwuert", + "So-so password" : "La-La Passwuert", + "Good password" : "Gutt Passwuert", + "Strong password" : "Staarkt Passwuert", "Shared" : "Gedeelt", "Error" : "Feeler", "Error while sharing" : "Feeler beim Deelen", "Error while unsharing" : "Feeler beim Annuléiere vum Deelen", "Error setting expiration date" : "Feeler beim Setze vum Verfallsdatum", + "The public link will expire no later than {days} days after it is created" : "Den ëffentleche Link wäert net méi spéit wéi {Deeg} Deeg nodeems et erstallt gouf verfalen ", "Set expiration date" : "Verfallsdatum setzen", + "Expiration" : "Leeft of", "Expiration date" : "Verfallsdatum", + "Choose a password for the public link" : "Wiel e Passwuert fir den ëffentleche Link aus", "Resharing is not allowed" : "Weiderdeelen ass net erlaabt", "Share link" : "Link deelen", + "Link" : "Link", "Password protect" : "Passwuertgeschützt", "Password" : "Passwuert", + "Allow editing" : "Beaarbechten erlaben", "Email link to person" : "Link enger Persoun mailen", "Send" : "Schécken", "Sending ..." : "Gëtt geschéckt...", @@ -78,6 +88,7 @@ OC.L10N.register( "Shared with you and the group {group} by {owner}" : "Gedeelt mat dir an der Grupp {group} vum {owner}", "Shared with you by {owner}" : "Gedeelt mat dir vum {owner}", "group" : "Grupp", + "remote" : "Op Distanz", "notify by email" : "via e-mail Bescheed ginn", "Unshare" : "Net méi deelen", "can share" : "kann deelen", @@ -87,6 +98,7 @@ OC.L10N.register( "delete" : "läschen", "access control" : "Zougrëffskontroll", "Share" : "Deelen", + "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Mat Leit vun aneren ownCloud deelen, déi d'Syntax username@example.com/owncloud benotzen", "Warning" : "Warnung", "Delete" : "Läschen", "Rename" : "Ëmbenennen", diff --git a/core/l10n/lb.json b/core/l10n/lb.json index e1cfc10d33c72..607c3e6abb777 100644 --- a/core/l10n/lb.json +++ b/core/l10n/lb.json @@ -58,17 +58,27 @@ "Continue" : "Weider", "(all selected)" : "(all ausgewielt)", "({count} selected)" : "({count} ausgewielt)", + "Very weak password" : "Ganz schwaacht Passwuert", + "Weak password" : "Schwaacht Passwuert", + "So-so password" : "La-La Passwuert", + "Good password" : "Gutt Passwuert", + "Strong password" : "Staarkt Passwuert", "Shared" : "Gedeelt", "Error" : "Feeler", "Error while sharing" : "Feeler beim Deelen", "Error while unsharing" : "Feeler beim Annuléiere vum Deelen", "Error setting expiration date" : "Feeler beim Setze vum Verfallsdatum", + "The public link will expire no later than {days} days after it is created" : "Den ëffentleche Link wäert net méi spéit wéi {Deeg} Deeg nodeems et erstallt gouf verfalen ", "Set expiration date" : "Verfallsdatum setzen", + "Expiration" : "Leeft of", "Expiration date" : "Verfallsdatum", + "Choose a password for the public link" : "Wiel e Passwuert fir den ëffentleche Link aus", "Resharing is not allowed" : "Weiderdeelen ass net erlaabt", "Share link" : "Link deelen", + "Link" : "Link", "Password protect" : "Passwuertgeschützt", "Password" : "Passwuert", + "Allow editing" : "Beaarbechten erlaben", "Email link to person" : "Link enger Persoun mailen", "Send" : "Schécken", "Sending ..." : "Gëtt geschéckt...", @@ -76,6 +86,7 @@ "Shared with you and the group {group} by {owner}" : "Gedeelt mat dir an der Grupp {group} vum {owner}", "Shared with you by {owner}" : "Gedeelt mat dir vum {owner}", "group" : "Grupp", + "remote" : "Op Distanz", "notify by email" : "via e-mail Bescheed ginn", "Unshare" : "Net méi deelen", "can share" : "kann deelen", @@ -85,6 +96,7 @@ "delete" : "läschen", "access control" : "Zougrëffskontroll", "Share" : "Deelen", + "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Mat Leit vun aneren ownCloud deelen, déi d'Syntax username@example.com/owncloud benotzen", "Warning" : "Warnung", "Delete" : "Läschen", "Rename" : "Ëmbenennen", diff --git a/lib/l10n/lb.js b/lib/l10n/lb.js index d74b2a40c1b63..0b87fdc1ef035 100644 --- a/lib/l10n/lb.js +++ b/lib/l10n/lb.js @@ -19,6 +19,8 @@ OC.L10N.register( "seconds ago" : "Sekonnen hir", "%s shared »%s« with you" : "Den/D' %s huet »%s« mat dir gedeelt", "Apps" : "Applikatiounen", + "A valid username must be provided" : "Et muss e gültegen Benotzernumm ugi ginn", + "A valid password must be provided" : "Et muss e gültegt Passwuert ugi ginn", "Help" : "Hëllef", "Personal" : "Perséinlech", "Users" : "Benotzer", diff --git a/lib/l10n/lb.json b/lib/l10n/lb.json index f1cfbd8858036..7015a7cacee33 100644 --- a/lib/l10n/lb.json +++ b/lib/l10n/lb.json @@ -17,6 +17,8 @@ "seconds ago" : "Sekonnen hir", "%s shared »%s« with you" : "Den/D' %s huet »%s« mat dir gedeelt", "Apps" : "Applikatiounen", + "A valid username must be provided" : "Et muss e gültegen Benotzernumm ugi ginn", + "A valid password must be provided" : "Et muss e gültegt Passwuert ugi ginn", "Help" : "Hëllef", "Personal" : "Perséinlech", "Users" : "Benotzer", diff --git a/settings/l10n/ar.js b/settings/l10n/ar.js index 96eeb9004e6d1..50de7c879528e 100644 --- a/settings/l10n/ar.js +++ b/settings/l10n/ar.js @@ -94,9 +94,9 @@ OC.L10N.register( "Language" : "اللغة", "Help translate" : "ساعد في الترجمه", "Name" : "الاسم", + "Username" : "إسم المستخدم", "Get the apps to sync your files" : "احصل على التطبيقات لمزامنة ملفاتك", "Show First Run Wizard again" : "ابدأ خطوات بداية التشغيل من جديد", - "Username" : "إسم المستخدم", "E-Mail" : "بريد إلكتروني", "Create" : "انشئ", "Admin Recovery Password" : "استعادة كلمة المرور للمسؤول", diff --git a/settings/l10n/ar.json b/settings/l10n/ar.json index d7033ff256665..e91d8dcc05c9a 100644 --- a/settings/l10n/ar.json +++ b/settings/l10n/ar.json @@ -92,9 +92,9 @@ "Language" : "اللغة", "Help translate" : "ساعد في الترجمه", "Name" : "الاسم", + "Username" : "إسم المستخدم", "Get the apps to sync your files" : "احصل على التطبيقات لمزامنة ملفاتك", "Show First Run Wizard again" : "ابدأ خطوات بداية التشغيل من جديد", - "Username" : "إسم المستخدم", "E-Mail" : "بريد إلكتروني", "Create" : "انشئ", "Admin Recovery Password" : "استعادة كلمة المرور للمسؤول", diff --git a/settings/l10n/ast.js b/settings/l10n/ast.js index 88f5a9c0a1f39..9a5033e6bbfb4 100644 --- a/settings/l10n/ast.js +++ b/settings/l10n/ast.js @@ -133,12 +133,12 @@ OC.L10N.register( "Language" : "Llingua", "Help translate" : "Ayúdanos nes traducciones", "Name" : "Nome", + "Username" : "Nome d'usuariu", "Get the apps to sync your files" : "Obtener les aplicaciones pa sincronizar ficheros", "Desktop client" : "Cliente d'escritoriu", "Android app" : "Aplicación d'Android", "iOS app" : "Aplicación d'iOS", "Show First Run Wizard again" : "Amosar nuevamente l'Encontu d'execución inicial", - "Username" : "Nome d'usuariu", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de la contraseña d'alministración", "Enter the recovery password in order to recover the users files during password change" : "Introduz la contraseña de recuperación col envís de recuperar los ficheros de los usuarios mientres el cambéu de contraseña.", diff --git a/settings/l10n/ast.json b/settings/l10n/ast.json index 70c61c9da5336..5578a0efffed3 100644 --- a/settings/l10n/ast.json +++ b/settings/l10n/ast.json @@ -131,12 +131,12 @@ "Language" : "Llingua", "Help translate" : "Ayúdanos nes traducciones", "Name" : "Nome", + "Username" : "Nome d'usuariu", "Get the apps to sync your files" : "Obtener les aplicaciones pa sincronizar ficheros", "Desktop client" : "Cliente d'escritoriu", "Android app" : "Aplicación d'Android", "iOS app" : "Aplicación d'iOS", "Show First Run Wizard again" : "Amosar nuevamente l'Encontu d'execución inicial", - "Username" : "Nome d'usuariu", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de la contraseña d'alministración", "Enter the recovery password in order to recover the users files during password change" : "Introduz la contraseña de recuperación col envís de recuperar los ficheros de los usuarios mientres el cambéu de contraseña.", diff --git a/settings/l10n/az.js b/settings/l10n/az.js index c9de6fb0c3b01..f8f811d516e21 100644 --- a/settings/l10n/az.js +++ b/settings/l10n/az.js @@ -186,6 +186,7 @@ OC.L10N.register( "Language" : "Dil", "Help translate" : "Tərcüməyə kömək", "Name" : "Ad", + "Username" : "İstifadəçi adı", "Done" : "Edildi", "Get the apps to sync your files" : "Fayllarınızın sinxronizasiyası üçün proqramları götürün", "Desktop client" : "Desktop client", @@ -199,7 +200,6 @@ OC.L10N.register( "Show user backend" : "Daxili istifadəçini göstər", "Send email to new user" : "Yeni istifadəçiyə məktub yolla", "Show email address" : "Email ünvanını göstər", - "Username" : "İstifadəçi adı", "E-Mail" : "E-Mail", "Create" : "Yarat", "Admin Recovery Password" : "İnzibatçı bərpa şifrəsi", diff --git a/settings/l10n/az.json b/settings/l10n/az.json index 37413d0e37d2e..50bb9278d0ad4 100644 --- a/settings/l10n/az.json +++ b/settings/l10n/az.json @@ -184,6 +184,7 @@ "Language" : "Dil", "Help translate" : "Tərcüməyə kömək", "Name" : "Ad", + "Username" : "İstifadəçi adı", "Done" : "Edildi", "Get the apps to sync your files" : "Fayllarınızın sinxronizasiyası üçün proqramları götürün", "Desktop client" : "Desktop client", @@ -197,7 +198,6 @@ "Show user backend" : "Daxili istifadəçini göstər", "Send email to new user" : "Yeni istifadəçiyə məktub yolla", "Show email address" : "Email ünvanını göstər", - "Username" : "İstifadəçi adı", "E-Mail" : "E-Mail", "Create" : "Yarat", "Admin Recovery Password" : "İnzibatçı bərpa şifrəsi", diff --git a/settings/l10n/bg_BG.js b/settings/l10n/bg_BG.js index 8a41c42474ca2..2a71d1bea0454 100644 --- a/settings/l10n/bg_BG.js +++ b/settings/l10n/bg_BG.js @@ -187,6 +187,7 @@ OC.L10N.register( "Language" : "Език", "Help translate" : "Помогни с превода", "Name" : "Име", + "Username" : "Потребителско Име", "Done" : "Завършен", "Get the apps to sync your files" : "Изтегли програми за синхронизиране на файловете ти", "Desktop client" : "Клиент за настолен компютър", @@ -199,7 +200,6 @@ OC.L10N.register( "Show last log in" : "Покажи последно вписване", "Send email to new user" : "Изпращай писмо към нов потребител", "Show email address" : "Покажи адреса на електронната поща", - "Username" : "Потребителско Име", "E-Mail" : "Електронна поща", "Create" : "Създаване", "Admin Recovery Password" : "Възстановяване на Администраторска Парола", diff --git a/settings/l10n/bg_BG.json b/settings/l10n/bg_BG.json index da25c47d90666..eadbbd091728f 100644 --- a/settings/l10n/bg_BG.json +++ b/settings/l10n/bg_BG.json @@ -185,6 +185,7 @@ "Language" : "Език", "Help translate" : "Помогни с превода", "Name" : "Име", + "Username" : "Потребителско Име", "Done" : "Завършен", "Get the apps to sync your files" : "Изтегли програми за синхронизиране на файловете ти", "Desktop client" : "Клиент за настолен компютър", @@ -197,7 +198,6 @@ "Show last log in" : "Покажи последно вписване", "Send email to new user" : "Изпращай писмо към нов потребител", "Show email address" : "Покажи адреса на електронната поща", - "Username" : "Потребителско Име", "E-Mail" : "Електронна поща", "Create" : "Създаване", "Admin Recovery Password" : "Възстановяване на Администраторска Парола", diff --git a/settings/l10n/bn_BD.js b/settings/l10n/bn_BD.js index d1d0ea94cb920..1dff9f04ab59e 100644 --- a/settings/l10n/bn_BD.js +++ b/settings/l10n/bn_BD.js @@ -63,10 +63,10 @@ OC.L10N.register( "Language" : "ভাষা", "Help translate" : "অনুবাদ করতে সহায়তা করুন", "Name" : "নাম", + "Username" : "ব্যবহারকারী", "Done" : "শেষ হলো", "Get the apps to sync your files" : "আপনার ফাইলসমূহ সিংক করতে অ্যাপস নিন", "Show First Run Wizard again" : "প্রথমবার চালানোর যাদুকর পূনরায় প্রদর্শন কর", - "Username" : "ব্যবহারকারী", "Create" : "তৈরী কর", "Admin Recovery Password" : "প্রশাসক পূণরূদ্ধার কুটশব্দ", "Add Group" : "গ্রুপ যোগ কর", diff --git a/settings/l10n/bn_BD.json b/settings/l10n/bn_BD.json index 7c1df5586011e..7fadc00d8f86e 100644 --- a/settings/l10n/bn_BD.json +++ b/settings/l10n/bn_BD.json @@ -61,10 +61,10 @@ "Language" : "ভাষা", "Help translate" : "অনুবাদ করতে সহায়তা করুন", "Name" : "নাম", + "Username" : "ব্যবহারকারী", "Done" : "শেষ হলো", "Get the apps to sync your files" : "আপনার ফাইলসমূহ সিংক করতে অ্যাপস নিন", "Show First Run Wizard again" : "প্রথমবার চালানোর যাদুকর পূনরায় প্রদর্শন কর", - "Username" : "ব্যবহারকারী", "Create" : "তৈরী কর", "Admin Recovery Password" : "প্রশাসক পূণরূদ্ধার কুটশব্দ", "Add Group" : "গ্রুপ যোগ কর", diff --git a/settings/l10n/bn_IN.js b/settings/l10n/bn_IN.js index 641711457c8ce..6f5e0ea6d8fe8 100644 --- a/settings/l10n/bn_IN.js +++ b/settings/l10n/bn_IN.js @@ -5,7 +5,7 @@ OC.L10N.register( "Delete" : "মুছে ফেলা", "Cancel" : "বাতিল করা", "Name" : "নাম", - "Get the apps to sync your files" : "আপনার ফাইল সিঙ্ক করার অ্যাপ পান", - "Username" : "ইউজারনেম" + "Username" : "ইউজারনেম", + "Get the apps to sync your files" : "আপনার ফাইল সিঙ্ক করার অ্যাপ পান" }, "nplurals=2; plural=(n != 1);"); diff --git a/settings/l10n/bn_IN.json b/settings/l10n/bn_IN.json index 8693dbb8beb8e..323858068eea9 100644 --- a/settings/l10n/bn_IN.json +++ b/settings/l10n/bn_IN.json @@ -3,7 +3,7 @@ "Delete" : "মুছে ফেলা", "Cancel" : "বাতিল করা", "Name" : "নাম", - "Get the apps to sync your files" : "আপনার ফাইল সিঙ্ক করার অ্যাপ পান", - "Username" : "ইউজারনেম" + "Username" : "ইউজারনেম", + "Get the apps to sync your files" : "আপনার ফাইল সিঙ্ক করার অ্যাপ পান" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/settings/l10n/bs.js b/settings/l10n/bs.js index fefc3ef7559dd..f11c7b43baa2e 100644 --- a/settings/l10n/bs.js +++ b/settings/l10n/bs.js @@ -154,6 +154,7 @@ OC.L10N.register( "Language" : "Jezik", "Help translate" : "Pomozi prevesti", "Name" : "Ime", + "Username" : "Korisničko ime", "Get the apps to sync your files" : "Koristite aplikacije za sinhronizaciju svojih datoteka", "Desktop client" : "Desktop klijent", "Android app" : "Android aplikacija", @@ -164,7 +165,6 @@ OC.L10N.register( "Show user backend" : "Prikaži korisničku pozadinu (backend)", "Send email to new user" : "Pošalji e-poštu novom korisniku", "Show email address" : "Prikaži adresu e-pošte", - "Username" : "Korisničko ime", "E-Mail" : "E-pošta", "Create" : "Kreiraj", "Admin Recovery Password" : "Admin lozinka za oporavak", diff --git a/settings/l10n/bs.json b/settings/l10n/bs.json index 3fc14020f6f05..09158a27daae9 100644 --- a/settings/l10n/bs.json +++ b/settings/l10n/bs.json @@ -152,6 +152,7 @@ "Language" : "Jezik", "Help translate" : "Pomozi prevesti", "Name" : "Ime", + "Username" : "Korisničko ime", "Get the apps to sync your files" : "Koristite aplikacije za sinhronizaciju svojih datoteka", "Desktop client" : "Desktop klijent", "Android app" : "Android aplikacija", @@ -162,7 +163,6 @@ "Show user backend" : "Prikaži korisničku pozadinu (backend)", "Send email to new user" : "Pošalji e-poštu novom korisniku", "Show email address" : "Prikaži adresu e-pošte", - "Username" : "Korisničko ime", "E-Mail" : "E-pošta", "Create" : "Kreiraj", "Admin Recovery Password" : "Admin lozinka za oporavak", diff --git a/settings/l10n/ca.js b/settings/l10n/ca.js index 127d268cef68c..407100a2017e5 100644 --- a/settings/l10n/ca.js +++ b/settings/l10n/ca.js @@ -211,6 +211,7 @@ OC.L10N.register( "Language" : "Idioma", "Help translate" : "Ajudeu-nos amb la traducció", "Name" : "Nom", + "Username" : "Nom d'usuari", "Get the apps to sync your files" : "Obtingueu les aplicacions per sincronitzar els vostres fitxers", "Desktop client" : "Client d'escriptori", "Android app" : "aplicació para Android", @@ -223,7 +224,6 @@ OC.L10N.register( "Show user backend" : "Mostrar backend d'usuari", "Send email to new user" : "Enviar correu electrònic al nou usuari", "Show email address" : "Mostrar l'adreça de correu electrònic", - "Username" : "Nom d'usuari", "E-Mail" : "E-mail", "Create" : "Crea", "Admin Recovery Password" : "Recuperació de contrasenya d'administrador", diff --git a/settings/l10n/ca.json b/settings/l10n/ca.json index 0d43ef445d47a..f0e4db16abac9 100644 --- a/settings/l10n/ca.json +++ b/settings/l10n/ca.json @@ -209,6 +209,7 @@ "Language" : "Idioma", "Help translate" : "Ajudeu-nos amb la traducció", "Name" : "Nom", + "Username" : "Nom d'usuari", "Get the apps to sync your files" : "Obtingueu les aplicacions per sincronitzar els vostres fitxers", "Desktop client" : "Client d'escriptori", "Android app" : "aplicació para Android", @@ -221,7 +222,6 @@ "Show user backend" : "Mostrar backend d'usuari", "Send email to new user" : "Enviar correu electrònic al nou usuari", "Show email address" : "Mostrar l'adreça de correu electrònic", - "Username" : "Nom d'usuari", "E-Mail" : "E-mail", "Create" : "Crea", "Admin Recovery Password" : "Recuperació de contrasenya d'administrador", diff --git a/settings/l10n/cs_CZ.js b/settings/l10n/cs_CZ.js index 704b1970b1487..2485825e0c337 100644 --- a/settings/l10n/cs_CZ.js +++ b/settings/l10n/cs_CZ.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Heslo aplikace je přihlašovací údaj umožňující aplikaci nebo přístroji přístup k %s účtu.", "App name" : "Jméno aplikace", "Create new app password" : "Vytvořit nové heslo aplikace", + "Username" : "Uživatelské jméno", "Done" : "Dokončeno", "Get the apps to sync your files" : "Získat aplikace pro synchronizaci vašich souborů", "Desktop client" : "Aplikace pro počítač", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Zobrazit uživatelskou podpůrnou vrstvu", "Send email to new user" : "Poslat email novému uživateli", "Show email address" : "Emailová adresa", - "Username" : "Uživatelské jméno", "E-Mail" : "Email", "Create" : "Vytvořit", "Admin Recovery Password" : "Heslo obnovy správce", diff --git a/settings/l10n/cs_CZ.json b/settings/l10n/cs_CZ.json index 30380cf6e3647..d4e206bc9fdbe 100644 --- a/settings/l10n/cs_CZ.json +++ b/settings/l10n/cs_CZ.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Heslo aplikace je přihlašovací údaj umožňující aplikaci nebo přístroji přístup k %s účtu.", "App name" : "Jméno aplikace", "Create new app password" : "Vytvořit nové heslo aplikace", + "Username" : "Uživatelské jméno", "Done" : "Dokončeno", "Get the apps to sync your files" : "Získat aplikace pro synchronizaci vašich souborů", "Desktop client" : "Aplikace pro počítač", @@ -290,7 +291,6 @@ "Show user backend" : "Zobrazit uživatelskou podpůrnou vrstvu", "Send email to new user" : "Poslat email novému uživateli", "Show email address" : "Emailová adresa", - "Username" : "Uživatelské jméno", "E-Mail" : "Email", "Create" : "Vytvořit", "Admin Recovery Password" : "Heslo obnovy správce", diff --git a/settings/l10n/da.js b/settings/l10n/da.js index 0e3ba48225179..00774a096822d 100644 --- a/settings/l10n/da.js +++ b/settings/l10n/da.js @@ -234,6 +234,7 @@ OC.L10N.register( "Language" : "Sprog", "Help translate" : "Hjælp med oversættelsen", "Name" : "Navn", + "Username" : "Brugernavn", "Done" : "Færdig", "Get the apps to sync your files" : "Hent applikationerne for at synkronisere dine filer", "Desktop client" : "Skrivebordsklient", @@ -247,7 +248,6 @@ OC.L10N.register( "Show user backend" : "Vis bruger-backend", "Send email to new user" : "Send e-mail til ny bruger", "Show email address" : "Vis e-mailadresse", - "Username" : "Brugernavn", "E-Mail" : "E-mail", "Create" : "Ny", "Admin Recovery Password" : "Administrator gendannelse kodeord", diff --git a/settings/l10n/da.json b/settings/l10n/da.json index b77cb15564a19..29bb3f75d08df 100644 --- a/settings/l10n/da.json +++ b/settings/l10n/da.json @@ -232,6 +232,7 @@ "Language" : "Sprog", "Help translate" : "Hjælp med oversættelsen", "Name" : "Navn", + "Username" : "Brugernavn", "Done" : "Færdig", "Get the apps to sync your files" : "Hent applikationerne for at synkronisere dine filer", "Desktop client" : "Skrivebordsklient", @@ -245,7 +246,6 @@ "Show user backend" : "Vis bruger-backend", "Send email to new user" : "Send e-mail til ny bruger", "Show email address" : "Vis e-mailadresse", - "Username" : "Brugernavn", "E-Mail" : "E-mail", "Create" : "Ny", "Admin Recovery Password" : "Administrator gendannelse kodeord", diff --git a/settings/l10n/de.js b/settings/l10n/de.js index 26c62170a0cf2..029497ea84f43 100644 --- a/settings/l10n/de.js +++ b/settings/l10n/de.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Ein App-Passwort ist ein Passwort, dass einer App oder einem Gerät erlaubt auf Ihren %s-Konto zuzugreifen.", "App name" : "App-Name", "Create new app password" : "Neues App-Passwort erstellen", + "Username" : "Benutzername", "Done" : "Erledigt", "Get the apps to sync your files" : "Lade die Apps zur Synchronisierung Deiner Daten herunter", "Desktop client" : "Desktop-Client", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Benutzer-Backend anzeigen", "Send email to new user" : "E-Mail an neuen Benutzer senden", "Show email address" : "E-Mail-Adresse anzeigen", - "Username" : "Benutzername", "E-Mail" : "E-Mail", "Create" : "Anlegen", "Admin Recovery Password" : "Admin-Wiederherstellungspasswort", diff --git a/settings/l10n/de.json b/settings/l10n/de.json index 3483ac763e002..891e031eec091 100644 --- a/settings/l10n/de.json +++ b/settings/l10n/de.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Ein App-Passwort ist ein Passwort, dass einer App oder einem Gerät erlaubt auf Ihren %s-Konto zuzugreifen.", "App name" : "App-Name", "Create new app password" : "Neues App-Passwort erstellen", + "Username" : "Benutzername", "Done" : "Erledigt", "Get the apps to sync your files" : "Lade die Apps zur Synchronisierung Deiner Daten herunter", "Desktop client" : "Desktop-Client", @@ -290,7 +291,6 @@ "Show user backend" : "Benutzer-Backend anzeigen", "Send email to new user" : "E-Mail an neuen Benutzer senden", "Show email address" : "E-Mail-Adresse anzeigen", - "Username" : "Benutzername", "E-Mail" : "E-Mail", "Create" : "Anlegen", "Admin Recovery Password" : "Admin-Wiederherstellungspasswort", diff --git a/settings/l10n/de_DE.js b/settings/l10n/de_DE.js index cb822ea9f8d3d..a40dd56f24b91 100644 --- a/settings/l10n/de_DE.js +++ b/settings/l10n/de_DE.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Ein App-Passwort ist ein Passwort, dass einer App oder einem Gerät erlaubt auf Ihren %s-Konto zuzugreifen.", "App name" : "App-Name", "Create new app password" : "Neues App-Passwort erstellen", + "Username" : "Benutzername", "Done" : "Erledigt", "Get the apps to sync your files" : "Installieren Sie die Anwendungen, um Ihre Dateien zu synchronisieren", "Desktop client" : "Desktop-Client", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Benutzer-Backend anzeigen", "Send email to new user" : "E-Mail an neuen Benutzer senden", "Show email address" : "E-Mail Adresse anzeigen", - "Username" : "Benutzername", "E-Mail" : "E-Mail", "Create" : "Erstellen", "Admin Recovery Password" : "Admin-Passwort-Wiederherstellung", diff --git a/settings/l10n/de_DE.json b/settings/l10n/de_DE.json index 0b6e3d7fdca08..4cedb8464ecf8 100644 --- a/settings/l10n/de_DE.json +++ b/settings/l10n/de_DE.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Ein App-Passwort ist ein Passwort, dass einer App oder einem Gerät erlaubt auf Ihren %s-Konto zuzugreifen.", "App name" : "App-Name", "Create new app password" : "Neues App-Passwort erstellen", + "Username" : "Benutzername", "Done" : "Erledigt", "Get the apps to sync your files" : "Installieren Sie die Anwendungen, um Ihre Dateien zu synchronisieren", "Desktop client" : "Desktop-Client", @@ -290,7 +291,6 @@ "Show user backend" : "Benutzer-Backend anzeigen", "Send email to new user" : "E-Mail an neuen Benutzer senden", "Show email address" : "E-Mail Adresse anzeigen", - "Username" : "Benutzername", "E-Mail" : "E-Mail", "Create" : "Erstellen", "Admin Recovery Password" : "Admin-Passwort-Wiederherstellung", diff --git a/settings/l10n/el.js b/settings/l10n/el.js index b79f5efa65dc5..f9f6575438c25 100644 --- a/settings/l10n/el.js +++ b/settings/l10n/el.js @@ -236,6 +236,7 @@ OC.L10N.register( "Language" : "Γλώσσα", "Help translate" : "Βοηθήστε στη μετάφραση", "Name" : "Όνομα", + "Username" : "Όνομα χρήστη", "Done" : "Ολοκληρώθηκε", "Get the apps to sync your files" : "Λήψη της εφαρμογής για συγχρονισμό των αρχείων σας", "Desktop client" : "Πελάτης σταθερού υπολογιστή", @@ -249,7 +250,6 @@ OC.L10N.register( "Show user backend" : "Εμφάνιση χρήστη συστήματος υποστήριξης", "Send email to new user" : "Αποστολή μηνύματος στο νέο χρήστη", "Show email address" : "Εμφάνιση διεύθυνσης ηλ. αλληλογραφίας", - "Username" : "Όνομα χρήστη", "E-Mail" : "Ηλεκτρονική αλληλογραφία", "Create" : "Δημιουργία", "Admin Recovery Password" : "Κωδικός Επαναφοράς Διαχειριστή ", diff --git a/settings/l10n/el.json b/settings/l10n/el.json index 623294c4f4049..f224a5f9a0278 100644 --- a/settings/l10n/el.json +++ b/settings/l10n/el.json @@ -234,6 +234,7 @@ "Language" : "Γλώσσα", "Help translate" : "Βοηθήστε στη μετάφραση", "Name" : "Όνομα", + "Username" : "Όνομα χρήστη", "Done" : "Ολοκληρώθηκε", "Get the apps to sync your files" : "Λήψη της εφαρμογής για συγχρονισμό των αρχείων σας", "Desktop client" : "Πελάτης σταθερού υπολογιστή", @@ -247,7 +248,6 @@ "Show user backend" : "Εμφάνιση χρήστη συστήματος υποστήριξης", "Send email to new user" : "Αποστολή μηνύματος στο νέο χρήστη", "Show email address" : "Εμφάνιση διεύθυνσης ηλ. αλληλογραφίας", - "Username" : "Όνομα χρήστη", "E-Mail" : "Ηλεκτρονική αλληλογραφία", "Create" : "Δημιουργία", "Admin Recovery Password" : "Κωδικός Επαναφοράς Διαχειριστή ", diff --git a/settings/l10n/en_GB.js b/settings/l10n/en_GB.js index f080b59c55383..2cd979acba7e7 100644 --- a/settings/l10n/en_GB.js +++ b/settings/l10n/en_GB.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "An app password is a passcode that gives an app or device permissions to access your %s account.", "App name" : "App name", "Create new app password" : "Create new app password", + "Username" : "Username", "Done" : "Done", "Get the apps to sync your files" : "Get the apps to sync your files", "Desktop client" : "Desktop client", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Show user backend", "Send email to new user" : "Send email to new user", "Show email address" : "Show email address", - "Username" : "Username", "E-Mail" : "E-Mail", "Create" : "Create", "Admin Recovery Password" : "Admin Recovery Password", diff --git a/settings/l10n/en_GB.json b/settings/l10n/en_GB.json index 203b5fde76e12..7370315c5f180 100644 --- a/settings/l10n/en_GB.json +++ b/settings/l10n/en_GB.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "An app password is a passcode that gives an app or device permissions to access your %s account.", "App name" : "App name", "Create new app password" : "Create new app password", + "Username" : "Username", "Done" : "Done", "Get the apps to sync your files" : "Get the apps to sync your files", "Desktop client" : "Desktop client", @@ -290,7 +291,6 @@ "Show user backend" : "Show user backend", "Send email to new user" : "Send email to new user", "Show email address" : "Show email address", - "Username" : "Username", "E-Mail" : "E-Mail", "Create" : "Create", "Admin Recovery Password" : "Admin Recovery Password", diff --git a/settings/l10n/eo.js b/settings/l10n/eo.js index 55bad706b82b9..4c77ddf264df5 100644 --- a/settings/l10n/eo.js +++ b/settings/l10n/eo.js @@ -125,6 +125,7 @@ OC.L10N.register( "Language" : "Lingvo", "Help translate" : "Helpu traduki", "Name" : "Nomo", + "Username" : "Uzantonomo", "Done" : "Farita", "Get the apps to sync your files" : "Ekhavu la aplikaĵojn por sinkronigi viajn dosierojn", "Desktop client" : "Labortabla kliento", @@ -132,7 +133,6 @@ OC.L10N.register( "iOS app" : "iOS-aplikaĵo", "Show last log in" : "Montri lastan ensaluton", "Show user backend" : "Montri uzantomotoron", - "Username" : "Uzantonomo", "E-Mail" : "Retpoŝtadreso", "Create" : "Krei", "Add Group" : "Aldoni grupon", diff --git a/settings/l10n/eo.json b/settings/l10n/eo.json index dc0d29c1de74b..e404bae79af96 100644 --- a/settings/l10n/eo.json +++ b/settings/l10n/eo.json @@ -123,6 +123,7 @@ "Language" : "Lingvo", "Help translate" : "Helpu traduki", "Name" : "Nomo", + "Username" : "Uzantonomo", "Done" : "Farita", "Get the apps to sync your files" : "Ekhavu la aplikaĵojn por sinkronigi viajn dosierojn", "Desktop client" : "Labortabla kliento", @@ -130,7 +131,6 @@ "iOS app" : "iOS-aplikaĵo", "Show last log in" : "Montri lastan ensaluton", "Show user backend" : "Montri uzantomotoron", - "Username" : "Uzantonomo", "E-Mail" : "Retpoŝtadreso", "Create" : "Krei", "Add Group" : "Aldoni grupon", diff --git a/settings/l10n/es.js b/settings/l10n/es.js index 9a16c8ea914fc..83c49ce8b4aa9 100644 --- a/settings/l10n/es.js +++ b/settings/l10n/es.js @@ -274,6 +274,7 @@ OC.L10N.register( "Browser" : "Navegador", "Most recent activity" : "Actividad más reciente", "Name" : "Nombre", + "Username" : "Nombre de usuario", "Done" : "Hecho", "Get the apps to sync your files" : "Obtener las aplicaciones para sincronizar sus archivos", "Desktop client" : "Cliente de escritorio", @@ -287,7 +288,6 @@ OC.L10N.register( "Show user backend" : "Mostrar motor de usuario", "Send email to new user" : "Enviar correo al usuario nuevo", "Show email address" : "Mostrar dirección de correo electrónico", - "Username" : "Nombre de usuario", "E-Mail" : "Correo electrónico", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de la contraseña de administración", diff --git a/settings/l10n/es.json b/settings/l10n/es.json index bd9cb270bbd7f..cfe244068ef36 100644 --- a/settings/l10n/es.json +++ b/settings/l10n/es.json @@ -272,6 +272,7 @@ "Browser" : "Navegador", "Most recent activity" : "Actividad más reciente", "Name" : "Nombre", + "Username" : "Nombre de usuario", "Done" : "Hecho", "Get the apps to sync your files" : "Obtener las aplicaciones para sincronizar sus archivos", "Desktop client" : "Cliente de escritorio", @@ -285,7 +286,6 @@ "Show user backend" : "Mostrar motor de usuario", "Send email to new user" : "Enviar correo al usuario nuevo", "Show email address" : "Mostrar dirección de correo electrónico", - "Username" : "Nombre de usuario", "E-Mail" : "Correo electrónico", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de la contraseña de administración", diff --git a/settings/l10n/es_AR.js b/settings/l10n/es_AR.js index 7c99d3e5d7a5b..555714a2bfeff 100644 --- a/settings/l10n/es_AR.js +++ b/settings/l10n/es_AR.js @@ -105,12 +105,12 @@ OC.L10N.register( "Language" : "Idioma", "Help translate" : "Ayudanos a traducir", "Name" : "Nombre", + "Username" : "Nombre de usuario", "Get the apps to sync your files" : "Obtené Apps para sincronizar tus archivos", "Desktop client" : "Cliente de escritorio", "Android app" : "App para Android", "iOS app" : "App para iOS", "Show First Run Wizard again" : "Mostrar de nuevo el asistente de primera ejecución", - "Username" : "Nombre de usuario", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de contraseña de administrador", "Enter the recovery password in order to recover the users files during password change" : "Ingresá la contraseña de recuperación para recuperar los archivos de usuario al cambiar contraseña", diff --git a/settings/l10n/es_AR.json b/settings/l10n/es_AR.json index 46cf5526f69e5..e737a875f611f 100644 --- a/settings/l10n/es_AR.json +++ b/settings/l10n/es_AR.json @@ -103,12 +103,12 @@ "Language" : "Idioma", "Help translate" : "Ayudanos a traducir", "Name" : "Nombre", + "Username" : "Nombre de usuario", "Get the apps to sync your files" : "Obtené Apps para sincronizar tus archivos", "Desktop client" : "Cliente de escritorio", "Android app" : "App para Android", "iOS app" : "App para iOS", "Show First Run Wizard again" : "Mostrar de nuevo el asistente de primera ejecución", - "Username" : "Nombre de usuario", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de contraseña de administrador", "Enter the recovery password in order to recover the users files during password change" : "Ingresá la contraseña de recuperación para recuperar los archivos de usuario al cambiar contraseña", diff --git a/settings/l10n/es_MX.js b/settings/l10n/es_MX.js index 3472c25389fad..eaf58bd0387a6 100644 --- a/settings/l10n/es_MX.js +++ b/settings/l10n/es_MX.js @@ -80,9 +80,9 @@ OC.L10N.register( "Language" : "Idioma", "Help translate" : "Ayúdanos a traducir", "Name" : "Nombre", + "Username" : "Nombre de usuario", "Get the apps to sync your files" : "Obtener las aplicaciones para sincronizar sus archivos", "Show First Run Wizard again" : "Mostrar nuevamente el Asistente de ejecución inicial", - "Username" : "Nombre de usuario", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de la contraseña de administración", "Enter the recovery password in order to recover the users files during password change" : "Introduzca la contraseña de recuperación a fin de recuperar los archivos de los usuarios durante el cambio de contraseña.", diff --git a/settings/l10n/es_MX.json b/settings/l10n/es_MX.json index cefc0f8c6e336..daba89fa289f3 100644 --- a/settings/l10n/es_MX.json +++ b/settings/l10n/es_MX.json @@ -78,9 +78,9 @@ "Language" : "Idioma", "Help translate" : "Ayúdanos a traducir", "Name" : "Nombre", + "Username" : "Nombre de usuario", "Get the apps to sync your files" : "Obtener las aplicaciones para sincronizar sus archivos", "Show First Run Wizard again" : "Mostrar nuevamente el Asistente de ejecución inicial", - "Username" : "Nombre de usuario", "Create" : "Crear", "Admin Recovery Password" : "Recuperación de la contraseña de administración", "Enter the recovery password in order to recover the users files during password change" : "Introduzca la contraseña de recuperación a fin de recuperar los archivos de los usuarios durante el cambio de contraseña.", diff --git a/settings/l10n/et_EE.js b/settings/l10n/et_EE.js index 8448dd500fde1..0695e032451f2 100644 --- a/settings/l10n/et_EE.js +++ b/settings/l10n/et_EE.js @@ -200,6 +200,7 @@ OC.L10N.register( "Language" : "Keel", "Help translate" : "Aita tõlkida", "Name" : "Nimi", + "Username" : "Kasutajanimi", "Done" : "Valmis", "Get the apps to sync your files" : "Hangi rakendusi failide sünkroniseerimiseks", "Desktop client" : "Töölaua klient", @@ -210,7 +211,6 @@ OC.L10N.register( "Show last log in" : "Viimane sisselogimine", "Send email to new user" : "Saada uuele kasutajale e-kiri", "Show email address" : "Näita e-posti aadressi", - "Username" : "Kasutajanimi", "E-Mail" : "E-post", "Create" : "Lisa", "Admin Recovery Password" : "Admini parooli taastamine", diff --git a/settings/l10n/et_EE.json b/settings/l10n/et_EE.json index 8d74443002d1c..ff27e1d36ae58 100644 --- a/settings/l10n/et_EE.json +++ b/settings/l10n/et_EE.json @@ -198,6 +198,7 @@ "Language" : "Keel", "Help translate" : "Aita tõlkida", "Name" : "Nimi", + "Username" : "Kasutajanimi", "Done" : "Valmis", "Get the apps to sync your files" : "Hangi rakendusi failide sünkroniseerimiseks", "Desktop client" : "Töölaua klient", @@ -208,7 +209,6 @@ "Show last log in" : "Viimane sisselogimine", "Send email to new user" : "Saada uuele kasutajale e-kiri", "Show email address" : "Näita e-posti aadressi", - "Username" : "Kasutajanimi", "E-Mail" : "E-post", "Create" : "Lisa", "Admin Recovery Password" : "Admini parooli taastamine", diff --git a/settings/l10n/eu.js b/settings/l10n/eu.js index a8703668ac238..636db8ccebfbf 100644 --- a/settings/l10n/eu.js +++ b/settings/l10n/eu.js @@ -164,6 +164,7 @@ OC.L10N.register( "Language" : "Hizkuntza", "Help translate" : "Lagundu itzultzen", "Name" : "Izena", + "Username" : "Erabiltzaile izena", "Done" : "Egina", "Get the apps to sync your files" : "Lortu aplikazioak zure fitxategiak sinkronizatzeko", "Desktop client" : "Mahaigaineko bezeroa", @@ -175,7 +176,6 @@ OC.L10N.register( "Show user backend" : "Bistaratu erabiltzaile motorra", "Send email to new user" : "Bidali eposta erabiltzaile berriari", "Show email address" : "Bistaratu eposta helbidea", - "Username" : "Erabiltzaile izena", "E-Mail" : "E-posta", "Create" : "Sortu", "Admin Recovery Password" : "Administratzailearen pasahitza berreskuratzea", diff --git a/settings/l10n/eu.json b/settings/l10n/eu.json index efb94b66a8a3f..992e2bf9119b3 100644 --- a/settings/l10n/eu.json +++ b/settings/l10n/eu.json @@ -162,6 +162,7 @@ "Language" : "Hizkuntza", "Help translate" : "Lagundu itzultzen", "Name" : "Izena", + "Username" : "Erabiltzaile izena", "Done" : "Egina", "Get the apps to sync your files" : "Lortu aplikazioak zure fitxategiak sinkronizatzeko", "Desktop client" : "Mahaigaineko bezeroa", @@ -173,7 +174,6 @@ "Show user backend" : "Bistaratu erabiltzaile motorra", "Send email to new user" : "Bidali eposta erabiltzaile berriari", "Show email address" : "Bistaratu eposta helbidea", - "Username" : "Erabiltzaile izena", "E-Mail" : "E-posta", "Create" : "Sortu", "Admin Recovery Password" : "Administratzailearen pasahitza berreskuratzea", diff --git a/settings/l10n/fa.js b/settings/l10n/fa.js index 591e7c429cfb2..09c3512832abc 100644 --- a/settings/l10n/fa.js +++ b/settings/l10n/fa.js @@ -189,6 +189,7 @@ OC.L10N.register( "Language" : "زبان", "Help translate" : "به ترجمه آن کمک کنید", "Name" : "نام", + "Username" : "نام کاربری", "Get the apps to sync your files" : "برنامه ها را دریافت کنید تا فایل هایتان را همگام سازید", "Desktop client" : "نرم افزار دسکتاپ", "Android app" : "اپ اندروید", @@ -198,7 +199,6 @@ OC.L10N.register( "Show last log in" : "نمایش اخرین ورود", "Send email to new user" : "ارسال ایمیل به کاربر جدید", "Show email address" : "نمایش پست الکترونیکی", - "Username" : "نام کاربری", "E-Mail" : "ایمیل", "Create" : "ایجاد کردن", "Admin Recovery Password" : "مدیریت بازیابی رمز عبور", diff --git a/settings/l10n/fa.json b/settings/l10n/fa.json index b1c27a0c265d7..bfe47d62c6f00 100644 --- a/settings/l10n/fa.json +++ b/settings/l10n/fa.json @@ -187,6 +187,7 @@ "Language" : "زبان", "Help translate" : "به ترجمه آن کمک کنید", "Name" : "نام", + "Username" : "نام کاربری", "Get the apps to sync your files" : "برنامه ها را دریافت کنید تا فایل هایتان را همگام سازید", "Desktop client" : "نرم افزار دسکتاپ", "Android app" : "اپ اندروید", @@ -196,7 +197,6 @@ "Show last log in" : "نمایش اخرین ورود", "Send email to new user" : "ارسال ایمیل به کاربر جدید", "Show email address" : "نمایش پست الکترونیکی", - "Username" : "نام کاربری", "E-Mail" : "ایمیل", "Create" : "ایجاد کردن", "Admin Recovery Password" : "مدیریت بازیابی رمز عبور", diff --git a/settings/l10n/fi_FI.js b/settings/l10n/fi_FI.js index 2d32dc527f933..4edc2128ac2ba 100644 --- a/settings/l10n/fi_FI.js +++ b/settings/l10n/fi_FI.js @@ -264,6 +264,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Sovellussalasana on suojakoodi, joka antaa sovellukselle tai laitteelle käyttöoikeuden %s-tiliisi.", "App name" : "Sovelluksen nimi", "Create new app password" : "Luo uusi sovellussalasana", + "Username" : "Käyttäjätunnus", "Done" : "Valmis", "Get the apps to sync your files" : "Aseta sovellukset synkronoimaan tiedostosi", "Desktop client" : "Työpöytäsovellus", @@ -277,7 +278,6 @@ OC.L10N.register( "Show user backend" : "Näytä käyttäjätaustaosa", "Send email to new user" : "Lähetä sähköpostia uudelle käyttäjälle", "Show email address" : "Näytä sähköpostiosoite", - "Username" : "Käyttäjätunnus", "E-Mail" : "Sähköposti", "Create" : "Luo", "Admin Recovery Password" : "Ylläpitäjän palautussalasana", diff --git a/settings/l10n/fi_FI.json b/settings/l10n/fi_FI.json index dddfd1067c57a..8d7e882579e6d 100644 --- a/settings/l10n/fi_FI.json +++ b/settings/l10n/fi_FI.json @@ -262,6 +262,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Sovellussalasana on suojakoodi, joka antaa sovellukselle tai laitteelle käyttöoikeuden %s-tiliisi.", "App name" : "Sovelluksen nimi", "Create new app password" : "Luo uusi sovellussalasana", + "Username" : "Käyttäjätunnus", "Done" : "Valmis", "Get the apps to sync your files" : "Aseta sovellukset synkronoimaan tiedostosi", "Desktop client" : "Työpöytäsovellus", @@ -275,7 +276,6 @@ "Show user backend" : "Näytä käyttäjätaustaosa", "Send email to new user" : "Lähetä sähköpostia uudelle käyttäjälle", "Show email address" : "Näytä sähköpostiosoite", - "Username" : "Käyttäjätunnus", "E-Mail" : "Sähköposti", "Create" : "Luo", "Admin Recovery Password" : "Ylläpitäjän palautussalasana", diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js index b20ccbe627f7a..ad98f51acfa56 100644 --- a/settings/l10n/fr.js +++ b/settings/l10n/fr.js @@ -272,6 +272,7 @@ OC.L10N.register( "Browser" : "Navigateur", "Most recent activity" : "Activité la plus récente", "Name" : "Nom", + "Username" : "Nom d'utilisateur", "Done" : "Terminé", "Get the apps to sync your files" : "Obtenez les applications de synchronisation de vos fichiers", "Desktop client" : "Client de bureau", @@ -285,7 +286,6 @@ OC.L10N.register( "Show user backend" : "Montrer la source de l'identifiant", "Send email to new user" : "Envoyer un e-mail aux utilisateurs créés", "Show email address" : "Afficher l'adresse e-mail", - "Username" : "Nom d'utilisateur", "E-Mail" : "E-Mail", "Create" : "Créer", "Admin Recovery Password" : "Mot de passe Administrateur de récupération", diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json index 90e241cfae3a5..fe130ae13596d 100644 --- a/settings/l10n/fr.json +++ b/settings/l10n/fr.json @@ -270,6 +270,7 @@ "Browser" : "Navigateur", "Most recent activity" : "Activité la plus récente", "Name" : "Nom", + "Username" : "Nom d'utilisateur", "Done" : "Terminé", "Get the apps to sync your files" : "Obtenez les applications de synchronisation de vos fichiers", "Desktop client" : "Client de bureau", @@ -283,7 +284,6 @@ "Show user backend" : "Montrer la source de l'identifiant", "Send email to new user" : "Envoyer un e-mail aux utilisateurs créés", "Show email address" : "Afficher l'adresse e-mail", - "Username" : "Nom d'utilisateur", "E-Mail" : "E-Mail", "Create" : "Créer", "Admin Recovery Password" : "Mot de passe Administrateur de récupération", diff --git a/settings/l10n/gl.js b/settings/l10n/gl.js index d9ecbc1213bee..aa5f1af099764 100644 --- a/settings/l10n/gl.js +++ b/settings/l10n/gl.js @@ -226,6 +226,7 @@ OC.L10N.register( "Language" : "Idioma", "Help translate" : "Axude na tradución", "Name" : "Nome", + "Username" : "Nome de usuario", "Done" : "Feito", "Get the apps to sync your files" : "Obteña as aplicacións para sincronizar os seus ficheiros", "Desktop client" : "Cliente de escritorio", @@ -239,7 +240,6 @@ OC.L10N.register( "Show user backend" : "Amosar a infraestrutura do usuario", "Send email to new user" : "Enviar correo ao novo usuario", "Show email address" : "Amosar o enderezo de correo", - "Username" : "Nome de usuario", "E-Mail" : "Correo-e", "Create" : "Crear", "Admin Recovery Password" : "Contrasinal de recuperación do administrador", diff --git a/settings/l10n/gl.json b/settings/l10n/gl.json index 4cab1d0756bae..16f44ea74cfaa 100644 --- a/settings/l10n/gl.json +++ b/settings/l10n/gl.json @@ -224,6 +224,7 @@ "Language" : "Idioma", "Help translate" : "Axude na tradución", "Name" : "Nome", + "Username" : "Nome de usuario", "Done" : "Feito", "Get the apps to sync your files" : "Obteña as aplicacións para sincronizar os seus ficheiros", "Desktop client" : "Cliente de escritorio", @@ -237,7 +238,6 @@ "Show user backend" : "Amosar a infraestrutura do usuario", "Send email to new user" : "Enviar correo ao novo usuario", "Show email address" : "Amosar o enderezo de correo", - "Username" : "Nome de usuario", "E-Mail" : "Correo-e", "Create" : "Crear", "Admin Recovery Password" : "Contrasinal de recuperación do administrador", diff --git a/settings/l10n/he.js b/settings/l10n/he.js index 644c3219a4caa..311e6e898b9a3 100644 --- a/settings/l10n/he.js +++ b/settings/l10n/he.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "סיסמת יישום הנה קוד סיסמא שמאפשרת ליישום או התקן הרשאות גישה לחשבון %s שלך.", "App name" : "שם יישום", "Create new app password" : "יצירת סיסמת יישום חדשה", + "Username" : "שם משתמש", "Done" : "הסתיים", "Get the apps to sync your files" : "קבלת היישומים לסנכרון הקבצים שלך", "Desktop client" : "מחשב אישי", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "הצגת צד אחורי למשתמש", "Send email to new user" : "שליחת דואר אלקטרוני למשתמש חדש", "Show email address" : "הצגת כתובת דואר אלקטרוני", - "Username" : "שם משתמש", "E-Mail" : "דואר אלקטרוני", "Create" : "יצירה", "Admin Recovery Password" : "סיסמת השחזור של המנהל", diff --git a/settings/l10n/he.json b/settings/l10n/he.json index 48953344b8353..54de8555fca4e 100644 --- a/settings/l10n/he.json +++ b/settings/l10n/he.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "סיסמת יישום הנה קוד סיסמא שמאפשרת ליישום או התקן הרשאות גישה לחשבון %s שלך.", "App name" : "שם יישום", "Create new app password" : "יצירת סיסמת יישום חדשה", + "Username" : "שם משתמש", "Done" : "הסתיים", "Get the apps to sync your files" : "קבלת היישומים לסנכרון הקבצים שלך", "Desktop client" : "מחשב אישי", @@ -290,7 +291,6 @@ "Show user backend" : "הצגת צד אחורי למשתמש", "Send email to new user" : "שליחת דואר אלקטרוני למשתמש חדש", "Show email address" : "הצגת כתובת דואר אלקטרוני", - "Username" : "שם משתמש", "E-Mail" : "דואר אלקטרוני", "Create" : "יצירה", "Admin Recovery Password" : "סיסמת השחזור של המנהל", diff --git a/settings/l10n/hr.js b/settings/l10n/hr.js index 04562940a6122..338d94e631c36 100644 --- a/settings/l10n/hr.js +++ b/settings/l10n/hr.js @@ -135,11 +135,11 @@ OC.L10N.register( "Language" : "Jezik", "Help translate" : "Pomozite prevesti", "Name" : "Naziv", + "Username" : "Korisničko ime", "Get the apps to sync your files" : "Koristite aplikacije za sinkronizaciju svojih datoteka", "Show First Run Wizard again" : "Opet pokažite First Run Wizard", "Show storage location" : "Prikaži mjesto pohrane", "Show last log in" : "Prikaži zadnje spajanje", - "Username" : "Korisničko ime", "Create" : "Kreirajte", "Admin Recovery Password" : "Admin lozinka za oporavak", "Enter the recovery password in order to recover the users files during password change" : "Unesite lozinku za oporavak da biste oporavili korisničke datoteke tijekom promjene lozinke", diff --git a/settings/l10n/hr.json b/settings/l10n/hr.json index 0d06db8f80a9a..569e26f180eaf 100644 --- a/settings/l10n/hr.json +++ b/settings/l10n/hr.json @@ -133,11 +133,11 @@ "Language" : "Jezik", "Help translate" : "Pomozite prevesti", "Name" : "Naziv", + "Username" : "Korisničko ime", "Get the apps to sync your files" : "Koristite aplikacije za sinkronizaciju svojih datoteka", "Show First Run Wizard again" : "Opet pokažite First Run Wizard", "Show storage location" : "Prikaži mjesto pohrane", "Show last log in" : "Prikaži zadnje spajanje", - "Username" : "Korisničko ime", "Create" : "Kreirajte", "Admin Recovery Password" : "Admin lozinka za oporavak", "Enter the recovery password in order to recover the users files during password change" : "Unesite lozinku za oporavak da biste oporavili korisničke datoteke tijekom promjene lozinke", diff --git a/settings/l10n/hu_HU.js b/settings/l10n/hu_HU.js index 396fd13f22ee8..9547e549c6cf1 100644 --- a/settings/l10n/hu_HU.js +++ b/settings/l10n/hu_HU.js @@ -261,6 +261,7 @@ OC.L10N.register( "Language" : "Nyelv", "Help translate" : "Segítsen a fordításban!", "Name" : "Név", + "Username" : "Felhasználónév", "Done" : "Kész", "Get the apps to sync your files" : "Töltse le az állományok szinkronizációjához szükséges programokat!", "Desktop client" : "Asztali kliens", @@ -274,7 +275,6 @@ OC.L10N.register( "Show user backend" : "Felhasználói háttér mutatása", "Send email to new user" : "E-mail küldése az új felhasználónak", "Show email address" : "E-mail cím megjelenítése", - "Username" : "Felhasználónév", "E-Mail" : "E-mail", "Create" : "Létrehozás", "Admin Recovery Password" : "Adminisztrátori jelszó az állományok visszanyerésére", diff --git a/settings/l10n/hu_HU.json b/settings/l10n/hu_HU.json index ea29613851ea7..2fdfc8eb87191 100644 --- a/settings/l10n/hu_HU.json +++ b/settings/l10n/hu_HU.json @@ -259,6 +259,7 @@ "Language" : "Nyelv", "Help translate" : "Segítsen a fordításban!", "Name" : "Név", + "Username" : "Felhasználónév", "Done" : "Kész", "Get the apps to sync your files" : "Töltse le az állományok szinkronizációjához szükséges programokat!", "Desktop client" : "Asztali kliens", @@ -272,7 +273,6 @@ "Show user backend" : "Felhasználói háttér mutatása", "Send email to new user" : "E-mail küldése az új felhasználónak", "Show email address" : "E-mail cím megjelenítése", - "Username" : "Felhasználónév", "E-Mail" : "E-mail", "Create" : "Létrehozás", "Admin Recovery Password" : "Adminisztrátori jelszó az állományok visszanyerésére", diff --git a/settings/l10n/ia.js b/settings/l10n/ia.js index e772ddb4e6842..0a2d257bc72c5 100644 --- a/settings/l10n/ia.js +++ b/settings/l10n/ia.js @@ -32,8 +32,8 @@ OC.L10N.register( "Language" : "Linguage", "Help translate" : "Adjuta a traducer", "Name" : "Nomine", - "Get the apps to sync your files" : "Obtene le apps (applicationes) pro synchronizar tu files", "Username" : "Nomine de usator", + "Get the apps to sync your files" : "Obtene le apps (applicationes) pro synchronizar tu files", "Create" : "Crear", "Group" : "Gruppo", "Default Quota" : "Quota predeterminate", diff --git a/settings/l10n/ia.json b/settings/l10n/ia.json index d8b66b087795b..aa4fe78d1cba5 100644 --- a/settings/l10n/ia.json +++ b/settings/l10n/ia.json @@ -30,8 +30,8 @@ "Language" : "Linguage", "Help translate" : "Adjuta a traducer", "Name" : "Nomine", - "Get the apps to sync your files" : "Obtene le apps (applicationes) pro synchronizar tu files", "Username" : "Nomine de usator", + "Get the apps to sync your files" : "Obtene le apps (applicationes) pro synchronizar tu files", "Create" : "Crear", "Group" : "Gruppo", "Default Quota" : "Quota predeterminate", diff --git a/settings/l10n/id.js b/settings/l10n/id.js index fbc57559584db..25cd0f3bbdf88 100644 --- a/settings/l10n/id.js +++ b/settings/l10n/id.js @@ -236,6 +236,7 @@ OC.L10N.register( "Language" : "Bahasa", "Help translate" : "Bantu menerjemahkan", "Name" : "Nama", + "Username" : "Nama pengguna", "Done" : "Selesai", "Get the apps to sync your files" : "Dapatkan aplikasi untuk sinkronisasi berkas Anda", "Desktop client" : "Klien desktop", @@ -249,7 +250,6 @@ OC.L10N.register( "Show user backend" : "Tampilkan pengguna backend", "Send email to new user" : "Kirim email kepada pengguna baru", "Show email address" : "Tampilkan alamat email", - "Username" : "Nama pengguna", "E-Mail" : "E-Mail", "Create" : "Buat", "Admin Recovery Password" : "Sandi pemulihan Admin", diff --git a/settings/l10n/id.json b/settings/l10n/id.json index 7ceb5374dbd09..dcb4303bc9a56 100644 --- a/settings/l10n/id.json +++ b/settings/l10n/id.json @@ -234,6 +234,7 @@ "Language" : "Bahasa", "Help translate" : "Bantu menerjemahkan", "Name" : "Nama", + "Username" : "Nama pengguna", "Done" : "Selesai", "Get the apps to sync your files" : "Dapatkan aplikasi untuk sinkronisasi berkas Anda", "Desktop client" : "Klien desktop", @@ -247,7 +248,6 @@ "Show user backend" : "Tampilkan pengguna backend", "Send email to new user" : "Kirim email kepada pengguna baru", "Show email address" : "Tampilkan alamat email", - "Username" : "Nama pengguna", "E-Mail" : "E-Mail", "Create" : "Buat", "Admin Recovery Password" : "Sandi pemulihan Admin", diff --git a/settings/l10n/is.js b/settings/l10n/is.js index aa870d28d516f..3dd8eaee7ca8f 100644 --- a/settings/l10n/is.js +++ b/settings/l10n/is.js @@ -246,6 +246,7 @@ OC.L10N.register( "Language" : "Tungumál", "Help translate" : "Hjálpa við þýðingu", "Name" : "Heiti", + "Username" : "Notandanafn", "Get the apps to sync your files" : "Náðu í forrit til að samstilla skrárnar þínar", "Desktop client" : "Skjáborðsforrit", "Android app" : "Android-forrit", @@ -258,7 +259,6 @@ OC.L10N.register( "Show user backend" : "Birta bakenda notanda", "Send email to new user" : "Senda tölvupóst til nýs notanda", "Show email address" : "Birta tölvupóstfang", - "Username" : "Notandanafn", "E-Mail" : "Tölvupóstfang", "Create" : "Búa til", "Admin Recovery Password" : "Endurheimtulykilorð kerfisstjóra", diff --git a/settings/l10n/is.json b/settings/l10n/is.json index 0f9291d1915b9..a37cf57d8b411 100644 --- a/settings/l10n/is.json +++ b/settings/l10n/is.json @@ -244,6 +244,7 @@ "Language" : "Tungumál", "Help translate" : "Hjálpa við þýðingu", "Name" : "Heiti", + "Username" : "Notandanafn", "Get the apps to sync your files" : "Náðu í forrit til að samstilla skrárnar þínar", "Desktop client" : "Skjáborðsforrit", "Android app" : "Android-forrit", @@ -256,7 +257,6 @@ "Show user backend" : "Birta bakenda notanda", "Send email to new user" : "Senda tölvupóst til nýs notanda", "Show email address" : "Birta tölvupóstfang", - "Username" : "Notandanafn", "E-Mail" : "Tölvupóstfang", "Create" : "Búa til", "Admin Recovery Password" : "Endurheimtulykilorð kerfisstjóra", diff --git a/settings/l10n/it.js b/settings/l10n/it.js index d877b7beafafc..6104c0bf3eb3b 100644 --- a/settings/l10n/it.js +++ b/settings/l10n/it.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Una password di applicazione è un codice di sicurezza che fornisce a un'applicazione o a un dispositivo i permessi per accedere al tuo account %s.", "App name" : "Nome applicazione", "Create new app password" : "Crea nuova password di applicazione", + "Username" : "Nome utente", "Done" : "Completato", "Get the apps to sync your files" : "Scarica le applicazioni per sincronizzare i tuoi file", "Desktop client" : "Client desktop", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Mostra il motore utente", "Send email to new user" : "Invia email al nuovo utente", "Show email address" : "Mostra l'indirizzo email", - "Username" : "Nome utente", "E-Mail" : "Posta elettronica", "Create" : "Crea", "Admin Recovery Password" : "Password di ripristino amministrativa", diff --git a/settings/l10n/it.json b/settings/l10n/it.json index 913fa6706b83a..f0fac257c4bdf 100644 --- a/settings/l10n/it.json +++ b/settings/l10n/it.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Una password di applicazione è un codice di sicurezza che fornisce a un'applicazione o a un dispositivo i permessi per accedere al tuo account %s.", "App name" : "Nome applicazione", "Create new app password" : "Crea nuova password di applicazione", + "Username" : "Nome utente", "Done" : "Completato", "Get the apps to sync your files" : "Scarica le applicazioni per sincronizzare i tuoi file", "Desktop client" : "Client desktop", @@ -290,7 +291,6 @@ "Show user backend" : "Mostra il motore utente", "Send email to new user" : "Invia email al nuovo utente", "Show email address" : "Mostra l'indirizzo email", - "Username" : "Nome utente", "E-Mail" : "Posta elettronica", "Create" : "Crea", "Admin Recovery Password" : "Password di ripristino amministrativa", diff --git a/settings/l10n/ja.js b/settings/l10n/ja.js index d4c8259b2ead5..11674827510ae 100644 --- a/settings/l10n/ja.js +++ b/settings/l10n/ja.js @@ -271,6 +271,7 @@ OC.L10N.register( "Browser" : "ブラウザ", "Most recent activity" : "最新のアクティビティ", "Name" : "名前", + "Username" : "ユーザーID", "Done" : "完了", "Get the apps to sync your files" : "ファイルを同期するアプリを取得しましょう", "Desktop client" : "デスクトップクライアント", @@ -284,7 +285,6 @@ OC.L10N.register( "Show user backend" : "ユーザーバックエンドを表示", "Send email to new user" : "新規ユーザーにメールを送信", "Show email address" : "メールアドレスを表示", - "Username" : "ユーザーID", "E-Mail" : "メール", "Create" : "作成", "Admin Recovery Password" : "管理者リカバリパスワード", diff --git a/settings/l10n/ja.json b/settings/l10n/ja.json index 6e8279fb49e8d..9d432d85db61c 100644 --- a/settings/l10n/ja.json +++ b/settings/l10n/ja.json @@ -269,6 +269,7 @@ "Browser" : "ブラウザ", "Most recent activity" : "最新のアクティビティ", "Name" : "名前", + "Username" : "ユーザーID", "Done" : "完了", "Get the apps to sync your files" : "ファイルを同期するアプリを取得しましょう", "Desktop client" : "デスクトップクライアント", @@ -282,7 +283,6 @@ "Show user backend" : "ユーザーバックエンドを表示", "Send email to new user" : "新規ユーザーにメールを送信", "Show email address" : "メールアドレスを表示", - "Username" : "ユーザーID", "E-Mail" : "メール", "Create" : "作成", "Admin Recovery Password" : "管理者リカバリパスワード", diff --git a/settings/l10n/ka_GE.js b/settings/l10n/ka_GE.js index 2d125ba7995c8..0db979f42c277 100644 --- a/settings/l10n/ka_GE.js +++ b/settings/l10n/ka_GE.js @@ -55,9 +55,9 @@ OC.L10N.register( "Language" : "ენა", "Help translate" : "თარგმნის დახმარება", "Name" : "სახელი", + "Username" : "მომხმარებლის სახელი", "Get the apps to sync your files" : "აპლიკაცია ფაილების სინქრონიზაციისთვის", "Show First Run Wizard again" : "მაჩვენე თავიდან გაშვებული ვიზარდი", - "Username" : "მომხმარებლის სახელი", "Create" : "შექმნა", "Default Quota" : "საწყისი ქვოტა", "Other" : "სხვა", diff --git a/settings/l10n/ka_GE.json b/settings/l10n/ka_GE.json index 11fb2e4e2d45b..0f53e61b90611 100644 --- a/settings/l10n/ka_GE.json +++ b/settings/l10n/ka_GE.json @@ -53,9 +53,9 @@ "Language" : "ენა", "Help translate" : "თარგმნის დახმარება", "Name" : "სახელი", + "Username" : "მომხმარებლის სახელი", "Get the apps to sync your files" : "აპლიკაცია ფაილების სინქრონიზაციისთვის", "Show First Run Wizard again" : "მაჩვენე თავიდან გაშვებული ვიზარდი", - "Username" : "მომხმარებლის სახელი", "Create" : "შექმნა", "Default Quota" : "საწყისი ქვოტა", "Other" : "სხვა", diff --git a/settings/l10n/km.js b/settings/l10n/km.js index a5de441b3616c..1b7f59ef236f3 100644 --- a/settings/l10n/km.js +++ b/settings/l10n/km.js @@ -74,9 +74,9 @@ OC.L10N.register( "Language" : "ភាសា", "Help translate" : "ជួយ​បក​ប្រែ", "Name" : "ឈ្មោះ", + "Username" : "ឈ្មោះ​អ្នកប្រើ", "Get the apps to sync your files" : "ដាក់​អោយកម្មវិធីផ្សេងៗ ​ធ្វើសមកាលកម្ម​ឯកសារ​អ្នក", "Show First Run Wizard again" : "បង្ហាញ First Run Wizard ម្តង​ទៀត", - "Username" : "ឈ្មោះ​អ្នកប្រើ", "Create" : "បង្កើត", "Admin Recovery Password" : "ការ​ស្វែង​រក​ពាក្យ​សម្ងាត់របស់ប្រធាន​វេបសាយ", "Other" : "ផ្សេងៗ", diff --git a/settings/l10n/km.json b/settings/l10n/km.json index 91f83037b420c..6b99c49cb8fb3 100644 --- a/settings/l10n/km.json +++ b/settings/l10n/km.json @@ -72,9 +72,9 @@ "Language" : "ភាសា", "Help translate" : "ជួយ​បក​ប្រែ", "Name" : "ឈ្មោះ", + "Username" : "ឈ្មោះ​អ្នកប្រើ", "Get the apps to sync your files" : "ដាក់​អោយកម្មវិធីផ្សេងៗ ​ធ្វើសមកាលកម្ម​ឯកសារ​អ្នក", "Show First Run Wizard again" : "បង្ហាញ First Run Wizard ម្តង​ទៀត", - "Username" : "ឈ្មោះ​អ្នកប្រើ", "Create" : "បង្កើត", "Admin Recovery Password" : "ការ​ស្វែង​រក​ពាក្យ​សម្ងាត់របស់ប្រធាន​វេបសាយ", "Other" : "ផ្សេងៗ", diff --git a/settings/l10n/ko.js b/settings/l10n/ko.js index b78566d33d2c9..4be2d81ee0221 100644 --- a/settings/l10n/ko.js +++ b/settings/l10n/ko.js @@ -253,6 +253,7 @@ OC.L10N.register( "Language" : "언어", "Help translate" : "번역 돕기", "Name" : "이름", + "Username" : "사용자 이름", "Done" : "완료", "Get the apps to sync your files" : "파일 동기화 앱 가져오기", "Desktop client" : "데스크톱 클라이언트", @@ -266,7 +267,6 @@ OC.L10N.register( "Show user backend" : "사용자 백엔드 보이기", "Send email to new user" : "새 사용자에게 이메일 보내기", "Show email address" : "이메일 주소 보이기", - "Username" : "사용자 이름", "E-Mail" : "이메일", "Create" : "만들기", "Admin Recovery Password" : "관리자 복구 암호", diff --git a/settings/l10n/ko.json b/settings/l10n/ko.json index 1296a0db26307..abf2fa3af3918 100644 --- a/settings/l10n/ko.json +++ b/settings/l10n/ko.json @@ -251,6 +251,7 @@ "Language" : "언어", "Help translate" : "번역 돕기", "Name" : "이름", + "Username" : "사용자 이름", "Done" : "완료", "Get the apps to sync your files" : "파일 동기화 앱 가져오기", "Desktop client" : "데스크톱 클라이언트", @@ -264,7 +265,6 @@ "Show user backend" : "사용자 백엔드 보이기", "Send email to new user" : "새 사용자에게 이메일 보내기", "Show email address" : "이메일 주소 보이기", - "Username" : "사용자 이름", "E-Mail" : "이메일", "Create" : "만들기", "Admin Recovery Password" : "관리자 복구 암호", diff --git a/settings/l10n/lb.js b/settings/l10n/lb.js index 42376d8202877..80bd1b1fe89b1 100644 --- a/settings/l10n/lb.js +++ b/settings/l10n/lb.js @@ -2,44 +2,219 @@ OC.L10N.register( "settings", { "Wrong password" : "Falscht Passwuert", + "No user supplied" : "Kee Benotzer ugebueden", "Authentication error" : "Authentifikatioun's Fehler", + "Unable to change password" : "Konnt Passwuert net änneren", "Enabled" : "Aktivéiert", + "Not enabled" : "Net aktivéiert", + "A problem occurred, please check your log files (Error: %s)" : "Et ass e Problem opgetrueden, w.e.g kuckt är Log Fichieren (Feeler: %s)", + "Migration Completed" : "D'Migratioun ass erfëllt", + "Group already exists." : "D'Grupp existéiert schonn", + "Unable to add group." : "Onmeiglech fir d'Grupp beizefügen.", + "Unable to delete group." : "Onmeiglech d'Grupp ze läschen.", + "log-level out of allowed range" : "Log-Level ass ausserhalb vum erlaabte Beräich", "Saved" : "Gespäichert", + "test email settings" : "Test Email Astellungen", + "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Während dem Schécke vun der Email ass e Problem opgetrueden. W.e.g kuckt är Astellungen no. (Feeler: %s)", "Email sent" : "Email geschéckt", + "You need to set your user email before being able to send test emails." : "Du muss deng Email-Adress konfiguréieren éiers de Test-Maile schécke kanns.", + "Invalid mail address" : "Ongëlteg Email Adress", + "A user with that name already exists." : "E Benotzer mat dësem Numm existéiert schonn.", + "Unable to create user." : "Onméiglech de Benotzer ze erschafen.", + "Your %s account was created" : "Däin %s Kont gouf erschaf", + "Unable to delete user." : "Onmeiglech fir de User zu läschen.", + "Forbidden" : "Net erlaabt", + "Invalid user" : "Ongëltege Benotzer", + "Unable to change mail address" : "Onméiglech d'Email Adress ze änneren.", "Email saved" : "E-mail gespäichert", + "Your full name has been changed." : "Äre ganzen Numm ass geännert ginn.", + "Unable to change full name" : "Onméiglech de ganzen Numm ze änneren.", "APCu" : "APCu", "Redis" : "Redis", + "Security & setup warnings" : "Sécherheets & Konfiguratiouns Warnung", "Sharing" : "Gedeelt", + "Server-side encryption" : "Verschlësselung vun der Säit vum Server", + "External Storage" : "Externt Lager", "Cron" : "Cron", + "Email server" : "Email Server", "Log" : "Log", + "Tips & tricks" : "Tipps & Tricken", "Updates" : "Updates", + "Couldn't remove app." : "D'App konnt net ewechgeholl ginn.", "Language changed" : "Sprooch huet geännert", "Invalid request" : "Ongülteg Requête", "Admins can't remove themself from the admin group" : "Admins kennen sech selwer net aus enger Admin Group läschen.", "Unable to add user to group %s" : "Onmeiglech User an Grupp ze sätzen %s", + "Unable to remove user from group %s" : "Onméiglech fir de Benotzer vum Grupp %s ewech ze huelen", + "Couldn't update app." : "D'App konnt net erweidert ginn.", + "Are you really sure you want add \"{domain}\" as trusted domain?" : "Bas du wierklech sécher dass de \"{Domän}\" als zouverlässeg Domän derbäi setzen wëlls?", + "Add trusted domain" : "Zouverlässeg Domän derbäi setzen", + "Migration in progress. Please wait until the migration is finished" : "D'Migratioun ass am gaangen. W.e.g waart bis d'Migratioun fäerdeg ass", + "Migration started …" : "D'Migratioun fänkt un ...", + "Sending..." : "Gëtt geschéckt...", + "Official" : "Offiziell", + "Approved" : "Accordéiert", + "Experimental" : "Experimentell", "All" : "All", + "No apps found for your version" : "Et gouf keng App fir deng Versioun fonnt", + "The app will be downloaded from the app store" : "D'App gëtt aus dem App Buttek erofgelueden", + "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Dës App ass net op Sécherheets Problemer getest ginn an ass nei oder bekannt fir onstabil ze sinn. Installéieren op eegene Risiko.", + "Update to %s" : "Update op %s", + "_You have %n app update pending_::_You have %n app updates pending_" : ["Du hues %n App Aktualiséierung opstoen","Du hues %n App Aktualiséierungen opstoen"], + "Please wait...." : "W.e.g. waarden...", + "Error while disabling app" : "Feeler beim App ofschalten", "Disable" : "Ofschalten", "Enable" : "Aschalten", + "Error while enabling app" : "Feeler beim App aschalten", + "Error: this app cannot be enabled because it makes the server unstable" : "Feeler: Dës App kann net ageschalt ginn well et de Server onstabil mécht", + "Error: could not disable broken app" : "Feeler: déi futti's App kann net ofgeschalt ginn", + "Error while disabling broken app" : "Feller beim Ofschalte vun der futtisser App", + "Updating...." : "Aktualiséieren...", + "Error while updating app" : "Feeler beim Aktualiséiere vun der App", + "Updated" : "Aktualiséiert", + "Uninstalling ...." : "Gëtt desinstalléiert ...", + "Error while uninstalling app" : "Feeler beim App desinstalléieren", + "Uninstall" : "Desinstalléieren", + "App update" : "App Aktualiséierung", + "No apps found for {query}" : "Keng Apps fonnt fir {Ufro}", + "Disconnect" : "Trennen", + "Error while loading browser sessions and device tokens" : "Feeler während d'Browser Sëtzunge an d'Token Geräter gelueden hunn", + "Error while creating device token" : "Feeler beim Erstelle vum Token Gerät", + "Error while deleting the token" : "Feeler beim Läsche vum Token", + "An error occurred. Please upload an ASCII-encoded PEM certificate." : "Et ass e Feeler opgetrueden. W.e.g. luet een ASCII-encodéierte PEM Zertifikat erop.", + "Valid until {date}" : "Gülteg bis {Datum}", "Delete" : "Läschen", + "An error occurred: {message}" : "Et ass e Fehler opgetrueden: {Noriicht}", + "Select a profile picture" : "Wiel e Profil Bild aus", + "Very weak password" : "Ganz schwaacht Passwuert", + "Weak password" : "Schwaacht Passwuert", + "So-so password" : "La-La Passwuert", + "Good password" : "Gutt Passwuert", + "Strong password" : "Staarkt Passwuert", "Groups" : "Gruppen", - "undo" : "réckgängeg man", - "never" : "ni", + "Unable to delete {objName}" : "Onmeiglech fir {objName} ze läschen", + "Error creating group: {message}" : "Feeler beim Erstelle vun der Grupp: {Noriicht}", + "A valid group name must be provided" : "Et muss e gültege Gruppen Numm ugi ginn", + "deleted {groupName}" : "Geläscht {GruppenNumm}", + "undo" : "Réckgängeg man", + "no group" : "Keng Grupp", + "never" : "Ni", + "deleted {userName}" : "Geläscht {Benotzernumm}", + "add group" : "Grupp bäisetzen", + "Changing the password will result in data loss, because data recovery is not available for this user" : "D'Passwuert ännere wäert e Verloscht vun den Daten provozéiere, well Daten zeréck gewannen ass net disponibel fir dëse Benotzer", + "A valid username must be provided" : "Et muss e gültegen Benotzernumm ugi ginn", + "Error creating user: {message}" : "Feeler beim Erstelle vum Benotzer: {Noriicht}", + "A valid password must be provided" : "Et muss e gültegt Passwuert ugi ginn", + "A valid email must be provided" : "Et muss eng gülteg Emails Adresse ugi ginn", "__language_name__" : "__language_name__", + "Unlimited" : "Onlimitéiert", + "Personal info" : "Perséinlech Informatioun", + "Sessions" : "Sëtzung", + "App passwords" : "App Passwierder", + "Sync clients" : "Sync vun de Clienten", + "Everything (fatal issues, errors, warnings, info, debug)" : "Alles (fatal Aspekter, Feeler, Warnungen, Informatiounen, Debug)", + "Info, warnings, errors and fatal issues" : " Informatiounen, Warnungen, Feeler a fatal Aspekter", + "Warnings, errors and fatal issues" : "Warnungen, Feeler a fatal Aspekter", + "Errors and fatal issues" : "Feeler a fatal Aspekter", + "Fatal issues only" : "Nëmmen fatal Aspekter", "None" : "Keng", "Login" : "Login", + "Plain" : "Kloer", + "SSL" : "SSL", + "TLS" : "TLS", + "This means that there might be problems with certain characters in file names." : "Dëst heescht dass Problemer mat bestëmmte Charaktere bei de Fichier Nimm optauche kéinten.", + "All checks passed." : "All d'Tester bestanen.", "Open documentation" : "Dokumentatioun opmaachen", "Allow apps to use the Share API" : "Erlab Apps d'Share API ze benotzen", + "Allow users to share via link" : "De Benotzer d'Deele via Link erlaben", + "Allow public uploads" : "Ëffentlechen Upload erlaaben", + "Enforce password protection" : "Passwuert Schutz forcéieren", + "Set default expiration date" : "E Standard Verfallsdatum setzen", + "Allow users to send mail notification for shared files" : "De Benotzer erlaben Email Notifikatiounen fir gedeelten Fichieren ze schécken", + "Expire after " : "Oflafen nom", "days" : "Deeg", + "Enforce expiration date" : "Verfallsdatum forcéieren", "Allow resharing" : "Resharing erlaben", + "Allow sharing with groups" : "Deele mat Gruppen erlaben", + "Restrict users to only share with users in their groups" : "Benotzer aschränken fir nëmmen mat Benotzer aus hirerem Grupp ze deelen", + "Exclude groups from sharing" : "Gruppe vum Deelen ausschléissen", + "These groups will still be able to receive shares, but not to initiate them." : "Dës Gruppe kënnen weiderhin Undeeler kréien, mee kënnen se net ufänken.", + "Last cron job execution: %s." : "Leschte Cron Job Ausféierung: %s.", + "Last cron job execution: %s. Something seems wrong." : "Leschte Cron Job Ausféierung: %s. Eppes schéngt net ze klappen.", + "Cron was not executed yet!" : "Cron ass nach net ausgefouert ginn!", + "Execute one task with each page loaded" : "Mat all geluedener Säit eng Aufgab ausféieren", + "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php ass als webcron Service registréiert fir cron.php all15 Minutten iwwer http opzeruffen.", + "Use system's cron service to call the cron.php file every 15 minutes." : "Dem System säi Cron Service benotze fir d'Cron.php Fichieren all 15 Minutten opzeruffen.", + "Enable server-side encryption" : "Verschlësselung vun der Säit vum Server erlaaben", + "Please read carefully before activating server-side encryption: " : "W.e.g. lies opmierksam éier d'Verschlësselung vun der Säit vum Server aktivéiert gëtt:", + "Be aware that encryption always increases the file size." : "Sief der bewosst dass Verschlësselung ëmmer d'Gréisst vum Fichier erhéicht.", + "This is the final warning: Do you really want to enable encryption?" : "Dëst ass déi lescht Warnung: Wëlls de wierklech d'Verschlësselung aschalten?", + "Enable encryption" : "Verschlësselung aschalten", + "No encryption module loaded, please enable an encryption module in the app menu." : "Kee Verschlësselungs Modul gelueden, w.e.g. schalt en Verschlësselungs Modul am App Menü an.", + "Select default encryption module:" : "Standard Verschlësselung Modul auswielen:", + "Start migration" : "Migratioun ufänke", + "This is used for sending out notifications." : "Dëst gëtt benotzt fir Notifikatiounen eraus ze schécken.", + "Send mode" : "Verschécke-Modus", + "Encryption" : "Verschlësselung", + "From address" : "Vun der Adresse", + "mail" : "Mail", + "Authentication method" : "Authentifizéierungs Method", "Authentication required" : "Authentifizéierung néideg", "Server address" : "Server Adress", "Port" : "Port", + "SMTP Username" : "SMTP Benotzernumm", + "SMTP Password" : "SMTP Passwuert", + "Test email settings" : "Email Astellungen testen", + "Send email" : "Email schécken", + "Download logfile" : "Log Fichier eroflueden", "More" : "Méi", "Less" : "Manner", + "What to log" : "Wat loggen", + "How to do backups" : "Wéi ee Backup'e mécht", + "Advanced monitoring" : "Erweidert Beobachtung", + "Performance tuning" : "Leeschtungs Optimiséierung", + "Improving the config.php" : "D'Verbesseren vum config.php", + "Version" : "Versioun", + "Developer documentation" : "Entwéckler Dokumentatioun", + "by %s" : "vum %s", + "%s-licensed" : "%s-lizenséiert", + "Documentation:" : "Dokumentatioun:", + "User documentation" : "Benotzer Dokumentatioun", + "Admin documentation" : "Admin Dokumentatioun", + "Visit website" : "D'Websäit besichen", + "Report a bug" : "E Feeler melden", + "Show description …" : "D'Beschreiwung weisen", + "Hide description …" : "D'Beschreiwung verstoppe", + "This app has an update available." : "Et gëtt eng Aktualiséierung fir dës App.", + "Enable only for specific groups" : "Nëmme fir spezifesch Gruppen aschalten", + "Uninstall App" : "D'App desinstalléieren", + "Enable experimental apps" : "Experimentell Apps aschalten", + "SSL Root Certificates" : "SSL Wuerzel Zertifikat", + "Common Name" : "Allgemengen Numm", + "Valid until" : "Gülteg bis", + "Issued By" : "Ausgestallt vum", + "Valid until %s" : "Gülteg bis %s", + "Import root certificate" : "Wuerzel Zertifikat importéieren", "Cheers!" : "Prost!", + "Administrator documentation" : "Administrator Dokumentatioun", + "Online documentation" : "Online Dokumentatioun", + "Forum" : "Forum", + "Issue tracker" : "Aspekter Tracker", + "Commercial support" : "Kommerziell Ennerstëtzung", + "You are using %s of %s" : "Du benotz %s vun %s", + "Profile picture" : "Profil Foto", + "Upload new" : "Nei eroplueden", + "Select from Files" : "Aus de Fichieren wielen", + "Remove image" : "D'Bild läschen", + "png or jpg, max. 20 MB" : "png oder jpg, max. 20 MB", + "Picture provided by original account" : "Bild vum Original Kont bereet gestallt", "Cancel" : "Ofbriechen", + "Choose as profile picture" : "Als Profil Foto auswielen", + "Full name" : "Ganzen Numm", + "No display name set" : "Keen Nickname festgesat", "Email" : "Email", "Your email address" : "Deng Email Adress", + "For password recovery and notifications" : "Fir d'Passwuert zeréck ze setzen an Notifikatiounen", "Password" : "Passwuert", "Unable to change your password" : "Konnt däin Passwuert net änneren", "Current password" : "Momentan 't Passwuert", @@ -47,16 +222,42 @@ OC.L10N.register( "Change password" : "Passwuert änneren", "Language" : "Sprooch", "Help translate" : "Hëllef iwwersetzen", + "Browser" : "Browser", + "Most recent activity" : "Rezentsten Aktivitéit", + "You've linked these apps." : "Du hues dës Apps verbonnen", "Name" : "Numm", - "Desktop client" : "Desktop-Programm", + "App name" : "App Numm", + "Create new app password" : "En neit App Passwuert erstellen", + "Username" : "Benotzernumm", + "Done" : "Gemaacht", + "Get the apps to sync your files" : "D'Apps op Fichieren syncen", + "Desktop client" : "Desktop Client", "Android app" : "Android-App", "iOS app" : "iOS-App", - "Username" : "Benotzernumm", + "Show storage location" : "Weis de Lagerungs Uert un", + "Show last log in" : "Leschte Login uweisen", + "Show user backend" : "Backend Benotzer uweisen", + "Send email to new user" : "Eng Email un d'nei Benotzer schécken", + "Show email address" : "Emails Adress uweisen", "E-Mail" : "E-Mail", "Create" : "Erstellen", + "Admin Recovery Password" : "Admin Passwuert zeréck stellen", + "Add Group" : "Grupp bäisetzen", "Group" : "Grupp", + "Everyone" : "Jiddereen", + "Admins" : "Admin", "Default Quota" : "Standard Quota", + "Please enter storage quota (ex: \"512 MB\" or \"12 GB\")" : "W.e.g. gëff Quota vum Lagerungs Uert un (wx. \"512 MB\" oder \"12 GB\")", "Other" : "Aner", - "Quota" : "Quota" + "Full Name" : "Ganzen Numm", + "Group Admin for" : "Gruppen Admin fir", + "Quota" : "Quota", + "Storage Location" : "Lagerungs Uert", + "User Backend" : "Backend Benotzer", + "Last Login" : "Lëschte Login", + "change full name" : "Ganzen Numm änneren", + "set new password" : "Neit Passwuert setzen", + "change email address" : "Emails Adress wiesselen", + "Default" : "Standard" }, "nplurals=2; plural=(n != 1);"); diff --git a/settings/l10n/lb.json b/settings/l10n/lb.json index d59f06cf83400..ae09e23764c4c 100644 --- a/settings/l10n/lb.json +++ b/settings/l10n/lb.json @@ -1,43 +1,218 @@ { "translations": { "Wrong password" : "Falscht Passwuert", + "No user supplied" : "Kee Benotzer ugebueden", "Authentication error" : "Authentifikatioun's Fehler", + "Unable to change password" : "Konnt Passwuert net änneren", "Enabled" : "Aktivéiert", + "Not enabled" : "Net aktivéiert", + "A problem occurred, please check your log files (Error: %s)" : "Et ass e Problem opgetrueden, w.e.g kuckt är Log Fichieren (Feeler: %s)", + "Migration Completed" : "D'Migratioun ass erfëllt", + "Group already exists." : "D'Grupp existéiert schonn", + "Unable to add group." : "Onmeiglech fir d'Grupp beizefügen.", + "Unable to delete group." : "Onmeiglech d'Grupp ze läschen.", + "log-level out of allowed range" : "Log-Level ass ausserhalb vum erlaabte Beräich", "Saved" : "Gespäichert", + "test email settings" : "Test Email Astellungen", + "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Während dem Schécke vun der Email ass e Problem opgetrueden. W.e.g kuckt är Astellungen no. (Feeler: %s)", "Email sent" : "Email geschéckt", + "You need to set your user email before being able to send test emails." : "Du muss deng Email-Adress konfiguréieren éiers de Test-Maile schécke kanns.", + "Invalid mail address" : "Ongëlteg Email Adress", + "A user with that name already exists." : "E Benotzer mat dësem Numm existéiert schonn.", + "Unable to create user." : "Onméiglech de Benotzer ze erschafen.", + "Your %s account was created" : "Däin %s Kont gouf erschaf", + "Unable to delete user." : "Onmeiglech fir de User zu läschen.", + "Forbidden" : "Net erlaabt", + "Invalid user" : "Ongëltege Benotzer", + "Unable to change mail address" : "Onméiglech d'Email Adress ze änneren.", "Email saved" : "E-mail gespäichert", + "Your full name has been changed." : "Äre ganzen Numm ass geännert ginn.", + "Unable to change full name" : "Onméiglech de ganzen Numm ze änneren.", "APCu" : "APCu", "Redis" : "Redis", + "Security & setup warnings" : "Sécherheets & Konfiguratiouns Warnung", "Sharing" : "Gedeelt", + "Server-side encryption" : "Verschlësselung vun der Säit vum Server", + "External Storage" : "Externt Lager", "Cron" : "Cron", + "Email server" : "Email Server", "Log" : "Log", + "Tips & tricks" : "Tipps & Tricken", "Updates" : "Updates", + "Couldn't remove app." : "D'App konnt net ewechgeholl ginn.", "Language changed" : "Sprooch huet geännert", "Invalid request" : "Ongülteg Requête", "Admins can't remove themself from the admin group" : "Admins kennen sech selwer net aus enger Admin Group läschen.", "Unable to add user to group %s" : "Onmeiglech User an Grupp ze sätzen %s", + "Unable to remove user from group %s" : "Onméiglech fir de Benotzer vum Grupp %s ewech ze huelen", + "Couldn't update app." : "D'App konnt net erweidert ginn.", + "Are you really sure you want add \"{domain}\" as trusted domain?" : "Bas du wierklech sécher dass de \"{Domän}\" als zouverlässeg Domän derbäi setzen wëlls?", + "Add trusted domain" : "Zouverlässeg Domän derbäi setzen", + "Migration in progress. Please wait until the migration is finished" : "D'Migratioun ass am gaangen. W.e.g waart bis d'Migratioun fäerdeg ass", + "Migration started …" : "D'Migratioun fänkt un ...", + "Sending..." : "Gëtt geschéckt...", + "Official" : "Offiziell", + "Approved" : "Accordéiert", + "Experimental" : "Experimentell", "All" : "All", + "No apps found for your version" : "Et gouf keng App fir deng Versioun fonnt", + "The app will be downloaded from the app store" : "D'App gëtt aus dem App Buttek erofgelueden", + "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Dës App ass net op Sécherheets Problemer getest ginn an ass nei oder bekannt fir onstabil ze sinn. Installéieren op eegene Risiko.", + "Update to %s" : "Update op %s", + "_You have %n app update pending_::_You have %n app updates pending_" : ["Du hues %n App Aktualiséierung opstoen","Du hues %n App Aktualiséierungen opstoen"], + "Please wait...." : "W.e.g. waarden...", + "Error while disabling app" : "Feeler beim App ofschalten", "Disable" : "Ofschalten", "Enable" : "Aschalten", + "Error while enabling app" : "Feeler beim App aschalten", + "Error: this app cannot be enabled because it makes the server unstable" : "Feeler: Dës App kann net ageschalt ginn well et de Server onstabil mécht", + "Error: could not disable broken app" : "Feeler: déi futti's App kann net ofgeschalt ginn", + "Error while disabling broken app" : "Feller beim Ofschalte vun der futtisser App", + "Updating...." : "Aktualiséieren...", + "Error while updating app" : "Feeler beim Aktualiséiere vun der App", + "Updated" : "Aktualiséiert", + "Uninstalling ...." : "Gëtt desinstalléiert ...", + "Error while uninstalling app" : "Feeler beim App desinstalléieren", + "Uninstall" : "Desinstalléieren", + "App update" : "App Aktualiséierung", + "No apps found for {query}" : "Keng Apps fonnt fir {Ufro}", + "Disconnect" : "Trennen", + "Error while loading browser sessions and device tokens" : "Feeler während d'Browser Sëtzunge an d'Token Geräter gelueden hunn", + "Error while creating device token" : "Feeler beim Erstelle vum Token Gerät", + "Error while deleting the token" : "Feeler beim Läsche vum Token", + "An error occurred. Please upload an ASCII-encoded PEM certificate." : "Et ass e Feeler opgetrueden. W.e.g. luet een ASCII-encodéierte PEM Zertifikat erop.", + "Valid until {date}" : "Gülteg bis {Datum}", "Delete" : "Läschen", + "An error occurred: {message}" : "Et ass e Fehler opgetrueden: {Noriicht}", + "Select a profile picture" : "Wiel e Profil Bild aus", + "Very weak password" : "Ganz schwaacht Passwuert", + "Weak password" : "Schwaacht Passwuert", + "So-so password" : "La-La Passwuert", + "Good password" : "Gutt Passwuert", + "Strong password" : "Staarkt Passwuert", "Groups" : "Gruppen", - "undo" : "réckgängeg man", - "never" : "ni", + "Unable to delete {objName}" : "Onmeiglech fir {objName} ze läschen", + "Error creating group: {message}" : "Feeler beim Erstelle vun der Grupp: {Noriicht}", + "A valid group name must be provided" : "Et muss e gültege Gruppen Numm ugi ginn", + "deleted {groupName}" : "Geläscht {GruppenNumm}", + "undo" : "Réckgängeg man", + "no group" : "Keng Grupp", + "never" : "Ni", + "deleted {userName}" : "Geläscht {Benotzernumm}", + "add group" : "Grupp bäisetzen", + "Changing the password will result in data loss, because data recovery is not available for this user" : "D'Passwuert ännere wäert e Verloscht vun den Daten provozéiere, well Daten zeréck gewannen ass net disponibel fir dëse Benotzer", + "A valid username must be provided" : "Et muss e gültegen Benotzernumm ugi ginn", + "Error creating user: {message}" : "Feeler beim Erstelle vum Benotzer: {Noriicht}", + "A valid password must be provided" : "Et muss e gültegt Passwuert ugi ginn", + "A valid email must be provided" : "Et muss eng gülteg Emails Adresse ugi ginn", "__language_name__" : "__language_name__", + "Unlimited" : "Onlimitéiert", + "Personal info" : "Perséinlech Informatioun", + "Sessions" : "Sëtzung", + "App passwords" : "App Passwierder", + "Sync clients" : "Sync vun de Clienten", + "Everything (fatal issues, errors, warnings, info, debug)" : "Alles (fatal Aspekter, Feeler, Warnungen, Informatiounen, Debug)", + "Info, warnings, errors and fatal issues" : " Informatiounen, Warnungen, Feeler a fatal Aspekter", + "Warnings, errors and fatal issues" : "Warnungen, Feeler a fatal Aspekter", + "Errors and fatal issues" : "Feeler a fatal Aspekter", + "Fatal issues only" : "Nëmmen fatal Aspekter", "None" : "Keng", "Login" : "Login", + "Plain" : "Kloer", + "SSL" : "SSL", + "TLS" : "TLS", + "This means that there might be problems with certain characters in file names." : "Dëst heescht dass Problemer mat bestëmmte Charaktere bei de Fichier Nimm optauche kéinten.", + "All checks passed." : "All d'Tester bestanen.", "Open documentation" : "Dokumentatioun opmaachen", "Allow apps to use the Share API" : "Erlab Apps d'Share API ze benotzen", + "Allow users to share via link" : "De Benotzer d'Deele via Link erlaben", + "Allow public uploads" : "Ëffentlechen Upload erlaaben", + "Enforce password protection" : "Passwuert Schutz forcéieren", + "Set default expiration date" : "E Standard Verfallsdatum setzen", + "Allow users to send mail notification for shared files" : "De Benotzer erlaben Email Notifikatiounen fir gedeelten Fichieren ze schécken", + "Expire after " : "Oflafen nom", "days" : "Deeg", + "Enforce expiration date" : "Verfallsdatum forcéieren", "Allow resharing" : "Resharing erlaben", + "Allow sharing with groups" : "Deele mat Gruppen erlaben", + "Restrict users to only share with users in their groups" : "Benotzer aschränken fir nëmmen mat Benotzer aus hirerem Grupp ze deelen", + "Exclude groups from sharing" : "Gruppe vum Deelen ausschléissen", + "These groups will still be able to receive shares, but not to initiate them." : "Dës Gruppe kënnen weiderhin Undeeler kréien, mee kënnen se net ufänken.", + "Last cron job execution: %s." : "Leschte Cron Job Ausféierung: %s.", + "Last cron job execution: %s. Something seems wrong." : "Leschte Cron Job Ausféierung: %s. Eppes schéngt net ze klappen.", + "Cron was not executed yet!" : "Cron ass nach net ausgefouert ginn!", + "Execute one task with each page loaded" : "Mat all geluedener Säit eng Aufgab ausféieren", + "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php ass als webcron Service registréiert fir cron.php all15 Minutten iwwer http opzeruffen.", + "Use system's cron service to call the cron.php file every 15 minutes." : "Dem System säi Cron Service benotze fir d'Cron.php Fichieren all 15 Minutten opzeruffen.", + "Enable server-side encryption" : "Verschlësselung vun der Säit vum Server erlaaben", + "Please read carefully before activating server-side encryption: " : "W.e.g. lies opmierksam éier d'Verschlësselung vun der Säit vum Server aktivéiert gëtt:", + "Be aware that encryption always increases the file size." : "Sief der bewosst dass Verschlësselung ëmmer d'Gréisst vum Fichier erhéicht.", + "This is the final warning: Do you really want to enable encryption?" : "Dëst ass déi lescht Warnung: Wëlls de wierklech d'Verschlësselung aschalten?", + "Enable encryption" : "Verschlësselung aschalten", + "No encryption module loaded, please enable an encryption module in the app menu." : "Kee Verschlësselungs Modul gelueden, w.e.g. schalt en Verschlësselungs Modul am App Menü an.", + "Select default encryption module:" : "Standard Verschlësselung Modul auswielen:", + "Start migration" : "Migratioun ufänke", + "This is used for sending out notifications." : "Dëst gëtt benotzt fir Notifikatiounen eraus ze schécken.", + "Send mode" : "Verschécke-Modus", + "Encryption" : "Verschlësselung", + "From address" : "Vun der Adresse", + "mail" : "Mail", + "Authentication method" : "Authentifizéierungs Method", "Authentication required" : "Authentifizéierung néideg", "Server address" : "Server Adress", "Port" : "Port", + "SMTP Username" : "SMTP Benotzernumm", + "SMTP Password" : "SMTP Passwuert", + "Test email settings" : "Email Astellungen testen", + "Send email" : "Email schécken", + "Download logfile" : "Log Fichier eroflueden", "More" : "Méi", "Less" : "Manner", + "What to log" : "Wat loggen", + "How to do backups" : "Wéi ee Backup'e mécht", + "Advanced monitoring" : "Erweidert Beobachtung", + "Performance tuning" : "Leeschtungs Optimiséierung", + "Improving the config.php" : "D'Verbesseren vum config.php", + "Version" : "Versioun", + "Developer documentation" : "Entwéckler Dokumentatioun", + "by %s" : "vum %s", + "%s-licensed" : "%s-lizenséiert", + "Documentation:" : "Dokumentatioun:", + "User documentation" : "Benotzer Dokumentatioun", + "Admin documentation" : "Admin Dokumentatioun", + "Visit website" : "D'Websäit besichen", + "Report a bug" : "E Feeler melden", + "Show description …" : "D'Beschreiwung weisen", + "Hide description …" : "D'Beschreiwung verstoppe", + "This app has an update available." : "Et gëtt eng Aktualiséierung fir dës App.", + "Enable only for specific groups" : "Nëmme fir spezifesch Gruppen aschalten", + "Uninstall App" : "D'App desinstalléieren", + "Enable experimental apps" : "Experimentell Apps aschalten", + "SSL Root Certificates" : "SSL Wuerzel Zertifikat", + "Common Name" : "Allgemengen Numm", + "Valid until" : "Gülteg bis", + "Issued By" : "Ausgestallt vum", + "Valid until %s" : "Gülteg bis %s", + "Import root certificate" : "Wuerzel Zertifikat importéieren", "Cheers!" : "Prost!", + "Administrator documentation" : "Administrator Dokumentatioun", + "Online documentation" : "Online Dokumentatioun", + "Forum" : "Forum", + "Issue tracker" : "Aspekter Tracker", + "Commercial support" : "Kommerziell Ennerstëtzung", + "You are using %s of %s" : "Du benotz %s vun %s", + "Profile picture" : "Profil Foto", + "Upload new" : "Nei eroplueden", + "Select from Files" : "Aus de Fichieren wielen", + "Remove image" : "D'Bild läschen", + "png or jpg, max. 20 MB" : "png oder jpg, max. 20 MB", + "Picture provided by original account" : "Bild vum Original Kont bereet gestallt", "Cancel" : "Ofbriechen", + "Choose as profile picture" : "Als Profil Foto auswielen", + "Full name" : "Ganzen Numm", + "No display name set" : "Keen Nickname festgesat", "Email" : "Email", "Your email address" : "Deng Email Adress", + "For password recovery and notifications" : "Fir d'Passwuert zeréck ze setzen an Notifikatiounen", "Password" : "Passwuert", "Unable to change your password" : "Konnt däin Passwuert net änneren", "Current password" : "Momentan 't Passwuert", @@ -45,16 +220,42 @@ "Change password" : "Passwuert änneren", "Language" : "Sprooch", "Help translate" : "Hëllef iwwersetzen", + "Browser" : "Browser", + "Most recent activity" : "Rezentsten Aktivitéit", + "You've linked these apps." : "Du hues dës Apps verbonnen", "Name" : "Numm", - "Desktop client" : "Desktop-Programm", + "App name" : "App Numm", + "Create new app password" : "En neit App Passwuert erstellen", + "Username" : "Benotzernumm", + "Done" : "Gemaacht", + "Get the apps to sync your files" : "D'Apps op Fichieren syncen", + "Desktop client" : "Desktop Client", "Android app" : "Android-App", "iOS app" : "iOS-App", - "Username" : "Benotzernumm", + "Show storage location" : "Weis de Lagerungs Uert un", + "Show last log in" : "Leschte Login uweisen", + "Show user backend" : "Backend Benotzer uweisen", + "Send email to new user" : "Eng Email un d'nei Benotzer schécken", + "Show email address" : "Emails Adress uweisen", "E-Mail" : "E-Mail", "Create" : "Erstellen", + "Admin Recovery Password" : "Admin Passwuert zeréck stellen", + "Add Group" : "Grupp bäisetzen", "Group" : "Grupp", + "Everyone" : "Jiddereen", + "Admins" : "Admin", "Default Quota" : "Standard Quota", + "Please enter storage quota (ex: \"512 MB\" or \"12 GB\")" : "W.e.g. gëff Quota vum Lagerungs Uert un (wx. \"512 MB\" oder \"12 GB\")", "Other" : "Aner", - "Quota" : "Quota" + "Full Name" : "Ganzen Numm", + "Group Admin for" : "Gruppen Admin fir", + "Quota" : "Quota", + "Storage Location" : "Lagerungs Uert", + "User Backend" : "Backend Benotzer", + "Last Login" : "Lëschte Login", + "change full name" : "Ganzen Numm änneren", + "set new password" : "Neit Passwuert setzen", + "change email address" : "Emails Adress wiesselen", + "Default" : "Standard" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/settings/l10n/lt_LT.js b/settings/l10n/lt_LT.js index 18b71c4553c6e..139a6f29ef65e 100644 --- a/settings/l10n/lt_LT.js +++ b/settings/l10n/lt_LT.js @@ -95,12 +95,12 @@ OC.L10N.register( "Language" : "Kalba", "Help translate" : "Padėkite išversti", "Name" : "Pavadinimas", + "Username" : "Prisijungimo vardas", "Get the apps to sync your files" : "Atsisiųskite programėlių, kad sinchronizuotumėte savo failus", "Desktop client" : "Darbastalio klientas", "Android app" : "Android programa", "iOS app" : "iOS programa", "Show First Run Wizard again" : "Rodyti pirmo karto vedlį dar kartą", - "Username" : "Prisijungimo vardas", "Create" : "Sukurti", "Admin Recovery Password" : "Administracinis atkūrimo slaptažodis", "Enter the recovery password in order to recover the users files during password change" : "Įveskite atkūrimo slaptažodį, kad atkurti naudotojo failus keičiant slaptažodį", diff --git a/settings/l10n/lt_LT.json b/settings/l10n/lt_LT.json index 4a26ae8bf7592..fb94e1f187204 100644 --- a/settings/l10n/lt_LT.json +++ b/settings/l10n/lt_LT.json @@ -93,12 +93,12 @@ "Language" : "Kalba", "Help translate" : "Padėkite išversti", "Name" : "Pavadinimas", + "Username" : "Prisijungimo vardas", "Get the apps to sync your files" : "Atsisiųskite programėlių, kad sinchronizuotumėte savo failus", "Desktop client" : "Darbastalio klientas", "Android app" : "Android programa", "iOS app" : "iOS programa", "Show First Run Wizard again" : "Rodyti pirmo karto vedlį dar kartą", - "Username" : "Prisijungimo vardas", "Create" : "Sukurti", "Admin Recovery Password" : "Administracinis atkūrimo slaptažodis", "Enter the recovery password in order to recover the users files during password change" : "Įveskite atkūrimo slaptažodį, kad atkurti naudotojo failus keičiant slaptažodį", diff --git a/settings/l10n/lv.js b/settings/l10n/lv.js index a24704e636097..c27a5c06ace48 100644 --- a/settings/l10n/lv.js +++ b/settings/l10n/lv.js @@ -137,6 +137,7 @@ OC.L10N.register( "Language" : "Valoda", "Help translate" : "Palīdzi tulkot", "Name" : "Nosaukums", + "Username" : "Lietotājvārds", "Done" : "Pabeigts", "Get the apps to sync your files" : "Saņem lietotnes, lai sinhronizētu savas datnes", "Desktop client" : "Darbvirsmas klients", @@ -145,7 +146,6 @@ OC.L10N.register( "Show First Run Wizard again" : "Vēlreiz rādīt pirmās palaišanas vedni", "Send email to new user" : "Sūtīt e-pastu jaunajam lietotājam", "Show email address" : "Rādīt e-pasta adreses", - "Username" : "Lietotājvārds", "E-Mail" : "E-pasts", "Create" : "Izveidot", "Admin Recovery Password" : "Administratora atgūšanas parole", diff --git a/settings/l10n/lv.json b/settings/l10n/lv.json index 990d454f2a06e..d9745171d6aeb 100644 --- a/settings/l10n/lv.json +++ b/settings/l10n/lv.json @@ -135,6 +135,7 @@ "Language" : "Valoda", "Help translate" : "Palīdzi tulkot", "Name" : "Nosaukums", + "Username" : "Lietotājvārds", "Done" : "Pabeigts", "Get the apps to sync your files" : "Saņem lietotnes, lai sinhronizētu savas datnes", "Desktop client" : "Darbvirsmas klients", @@ -143,7 +144,6 @@ "Show First Run Wizard again" : "Vēlreiz rādīt pirmās palaišanas vedni", "Send email to new user" : "Sūtīt e-pastu jaunajam lietotājam", "Show email address" : "Rādīt e-pasta adreses", - "Username" : "Lietotājvārds", "E-Mail" : "E-pasts", "Create" : "Izveidot", "Admin Recovery Password" : "Administratora atgūšanas parole", diff --git a/settings/l10n/mk.js b/settings/l10n/mk.js index 088ea3c14db60..8eedc55b6e0de 100644 --- a/settings/l10n/mk.js +++ b/settings/l10n/mk.js @@ -168,9 +168,9 @@ OC.L10N.register( "Language" : "Јазик", "Help translate" : "Помогни во преводот", "Name" : "Име", + "Username" : "Корисничко име", "Get the apps to sync your files" : "Преземете апликации за синхронизирање на вашите датотеки", "Show First Run Wizard again" : "Прикажи го повторно волшебникот при првото стартување", - "Username" : "Корисничко име", "Create" : "Создај", "Admin Recovery Password" : "Обновување на Admin лозинката", "Add Group" : "Додади група", diff --git a/settings/l10n/mk.json b/settings/l10n/mk.json index 169f2328fbe1a..017cf4b081ad7 100644 --- a/settings/l10n/mk.json +++ b/settings/l10n/mk.json @@ -166,9 +166,9 @@ "Language" : "Јазик", "Help translate" : "Помогни во преводот", "Name" : "Име", + "Username" : "Корисничко име", "Get the apps to sync your files" : "Преземете апликации за синхронизирање на вашите датотеки", "Show First Run Wizard again" : "Прикажи го повторно волшебникот при првото стартување", - "Username" : "Корисничко име", "Create" : "Создај", "Admin Recovery Password" : "Обновување на Admin лозинката", "Add Group" : "Додади група", diff --git a/settings/l10n/mn.js b/settings/l10n/mn.js index 0bc562b05f76b..6a035bdfb56e6 100644 --- a/settings/l10n/mn.js +++ b/settings/l10n/mn.js @@ -15,7 +15,7 @@ OC.L10N.register( "All" : "Бүгд", "Email" : "И-мэйл", "Password" : "Нууц үг", - "Done" : "Болсон", - "Username" : "Хэрэглэгчийн нэр" + "Username" : "Хэрэглэгчийн нэр", + "Done" : "Болсон" }, "nplurals=2; plural=(n != 1);"); diff --git a/settings/l10n/mn.json b/settings/l10n/mn.json index 1f888f6ef2daf..f6634fd258749 100644 --- a/settings/l10n/mn.json +++ b/settings/l10n/mn.json @@ -13,7 +13,7 @@ "All" : "Бүгд", "Email" : "И-мэйл", "Password" : "Нууц үг", - "Done" : "Болсон", - "Username" : "Хэрэглэгчийн нэр" + "Username" : "Хэрэглэгчийн нэр", + "Done" : "Болсон" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/settings/l10n/nb_NO.js b/settings/l10n/nb_NO.js index faa4e92b0212c..25a6538d9b9a9 100644 --- a/settings/l10n/nb_NO.js +++ b/settings/l10n/nb_NO.js @@ -262,6 +262,7 @@ OC.L10N.register( "Language" : "Språk", "Help translate" : "Bidra til oversettelsen", "Name" : "Navn", + "Username" : "Brukernavn", "Done" : "Ferdig", "Get the apps to sync your files" : "Hent apper som synkroniserer filene dine", "Desktop client" : "Skrivebordsklient", @@ -275,7 +276,6 @@ OC.L10N.register( "Show user backend" : "Vis bruker-server", "Send email to new user" : "Send e-post til ny bruker", "Show email address" : "Vis e-postadresse", - "Username" : "Brukernavn", "E-Mail" : "E-post", "Create" : "Opprett", "Admin Recovery Password" : "Administrativt gjenopprettingspassord", diff --git a/settings/l10n/nb_NO.json b/settings/l10n/nb_NO.json index d094142fc6c5d..cf6766d862c48 100644 --- a/settings/l10n/nb_NO.json +++ b/settings/l10n/nb_NO.json @@ -260,6 +260,7 @@ "Language" : "Språk", "Help translate" : "Bidra til oversettelsen", "Name" : "Navn", + "Username" : "Brukernavn", "Done" : "Ferdig", "Get the apps to sync your files" : "Hent apper som synkroniserer filene dine", "Desktop client" : "Skrivebordsklient", @@ -273,7 +274,6 @@ "Show user backend" : "Vis bruker-server", "Send email to new user" : "Send e-post til ny bruker", "Show email address" : "Vis e-postadresse", - "Username" : "Brukernavn", "E-Mail" : "E-post", "Create" : "Opprett", "Admin Recovery Password" : "Administrativt gjenopprettingspassord", diff --git a/settings/l10n/nl.js b/settings/l10n/nl.js index 3938755e9740f..800ae67042812 100644 --- a/settings/l10n/nl.js +++ b/settings/l10n/nl.js @@ -274,6 +274,7 @@ OC.L10N.register( "Browser" : "Browser", "Most recent activity" : "Meest recente activiteit", "Name" : "Naam", + "Username" : "Gebruikersnaam", "Done" : "Gedaan", "Get the apps to sync your files" : "Download de apps om bestanden te synchroniseren", "Desktop client" : "Desktop client", @@ -287,7 +288,6 @@ OC.L10N.register( "Show user backend" : "Toon backend gebruiker", "Send email to new user" : "Verstuur e-mail aan nieuwe gebruiker", "Show email address" : "Toon e-mailadres", - "Username" : "Gebruikersnaam", "E-Mail" : "E-mail", "Create" : "Aanmaken", "Admin Recovery Password" : "Beheer herstel wachtwoord", diff --git a/settings/l10n/nl.json b/settings/l10n/nl.json index 696812dc8e865..660e4acce5851 100644 --- a/settings/l10n/nl.json +++ b/settings/l10n/nl.json @@ -272,6 +272,7 @@ "Browser" : "Browser", "Most recent activity" : "Meest recente activiteit", "Name" : "Naam", + "Username" : "Gebruikersnaam", "Done" : "Gedaan", "Get the apps to sync your files" : "Download de apps om bestanden te synchroniseren", "Desktop client" : "Desktop client", @@ -285,7 +286,6 @@ "Show user backend" : "Toon backend gebruiker", "Send email to new user" : "Verstuur e-mail aan nieuwe gebruiker", "Show email address" : "Toon e-mailadres", - "Username" : "Gebruikersnaam", "E-Mail" : "E-mail", "Create" : "Aanmaken", "Admin Recovery Password" : "Beheer herstel wachtwoord", diff --git a/settings/l10n/nn_NO.js b/settings/l10n/nn_NO.js index 33421d700bd36..e72e43579511f 100644 --- a/settings/l10n/nn_NO.js +++ b/settings/l10n/nn_NO.js @@ -68,9 +68,9 @@ OC.L10N.register( "Language" : "Språk", "Help translate" : "Hjelp oss å omsetja", "Name" : "Namn", + "Username" : "Brukarnamn", "Get the apps to sync your files" : "Få app-ar som kan synkronisera filene dine", "Show First Run Wizard again" : "Vis Oppstartvegvisaren igjen", - "Username" : "Brukarnamn", "Create" : "Lag", "Admin Recovery Password" : "Gjenopprettingspassord for administrator", "Enter the recovery password in order to recover the users files during password change" : "Skriv inn gjenopprettingspassordet brukt for å gjenoppretta brukarfilene ved passordendring", diff --git a/settings/l10n/nn_NO.json b/settings/l10n/nn_NO.json index 14b0aea0bcb03..58da1cecf0433 100644 --- a/settings/l10n/nn_NO.json +++ b/settings/l10n/nn_NO.json @@ -66,9 +66,9 @@ "Language" : "Språk", "Help translate" : "Hjelp oss å omsetja", "Name" : "Namn", + "Username" : "Brukarnamn", "Get the apps to sync your files" : "Få app-ar som kan synkronisera filene dine", "Show First Run Wizard again" : "Vis Oppstartvegvisaren igjen", - "Username" : "Brukarnamn", "Create" : "Lag", "Admin Recovery Password" : "Gjenopprettingspassord for administrator", "Enter the recovery password in order to recover the users files during password change" : "Skriv inn gjenopprettingspassordet brukt for å gjenoppretta brukarfilene ved passordendring", diff --git a/settings/l10n/oc.js b/settings/l10n/oc.js index 7ae654d1f4e99..4cee3292b71f6 100644 --- a/settings/l10n/oc.js +++ b/settings/l10n/oc.js @@ -237,6 +237,7 @@ OC.L10N.register( "Language" : "Lenga", "Help translate" : "Ajudatz a tradusir", "Name" : "Nom", + "Username" : "Nom d'utilizaire", "Get the apps to sync your files" : "Obtenètz las aplicacions de sincronizacion de vòstres fichièrs", "Desktop client" : "Client de burèu", "Android app" : "Aplicacion Android", @@ -249,7 +250,6 @@ OC.L10N.register( "Show user backend" : "Far veire la font de l'identificant", "Send email to new user" : "Mandar un corrièl als utilizaires creats", "Show email address" : "Afichar l'adreça email", - "Username" : "Nom d'utilizaire", "E-Mail" : "Corrièl", "Create" : "Crear", "Admin Recovery Password" : "Recuperacion del senhal administrator", diff --git a/settings/l10n/oc.json b/settings/l10n/oc.json index dd4eefe026a08..9a8568a2c7a41 100644 --- a/settings/l10n/oc.json +++ b/settings/l10n/oc.json @@ -235,6 +235,7 @@ "Language" : "Lenga", "Help translate" : "Ajudatz a tradusir", "Name" : "Nom", + "Username" : "Nom d'utilizaire", "Get the apps to sync your files" : "Obtenètz las aplicacions de sincronizacion de vòstres fichièrs", "Desktop client" : "Client de burèu", "Android app" : "Aplicacion Android", @@ -247,7 +248,6 @@ "Show user backend" : "Far veire la font de l'identificant", "Send email to new user" : "Mandar un corrièl als utilizaires creats", "Show email address" : "Afichar l'adreça email", - "Username" : "Nom d'utilizaire", "E-Mail" : "Corrièl", "Create" : "Crear", "Admin Recovery Password" : "Recuperacion del senhal administrator", diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js index 903b374e0af01..733b4a984424b 100644 --- a/settings/l10n/pl.js +++ b/settings/l10n/pl.js @@ -196,6 +196,7 @@ OC.L10N.register( "Language" : "Język", "Help translate" : "Pomóż w tłumaczeniu", "Name" : "Nazwa", + "Username" : "Nazwa użytkownika", "Done" : "Ukończono", "Get the apps to sync your files" : "Pobierz aplikacje żeby synchronizować swoje pliki", "Desktop client" : "Klient na komputer", @@ -207,7 +208,6 @@ OC.L10N.register( "Show user backend" : "Pokaż moduł użytkownika", "Send email to new user" : "Wyślij email do nowego użytkownika", "Show email address" : "Pokaż adres email", - "Username" : "Nazwa użytkownika", "E-Mail" : "E-mail", "Create" : "Utwórz", "Admin Recovery Password" : "Odzyskiwanie hasła administratora", diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json index f1c1994dd1d66..7540d5a6daa6d 100644 --- a/settings/l10n/pl.json +++ b/settings/l10n/pl.json @@ -194,6 +194,7 @@ "Language" : "Język", "Help translate" : "Pomóż w tłumaczeniu", "Name" : "Nazwa", + "Username" : "Nazwa użytkownika", "Done" : "Ukończono", "Get the apps to sync your files" : "Pobierz aplikacje żeby synchronizować swoje pliki", "Desktop client" : "Klient na komputer", @@ -205,7 +206,6 @@ "Show user backend" : "Pokaż moduł użytkownika", "Send email to new user" : "Wyślij email do nowego użytkownika", "Show email address" : "Pokaż adres email", - "Username" : "Nazwa użytkownika", "E-Mail" : "E-mail", "Create" : "Utwórz", "Admin Recovery Password" : "Odzyskiwanie hasła administratora", diff --git a/settings/l10n/pt_BR.js b/settings/l10n/pt_BR.js index 3e8c0da81ce94..3f4cbff71adbc 100644 --- a/settings/l10n/pt_BR.js +++ b/settings/l10n/pt_BR.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "A senha do aplicativo é um código de acesso que dá ao aplicativo ou dispositivo permissões para acessar sua conta %s.", "App name" : "Nome do aplicativo", "Create new app password" : "Criar uma nova senha do aplicativo", + "Username" : "Nome de Usuário", "Done" : "Concluída", "Get the apps to sync your files" : "Obtenha apps para sincronizar seus arquivos", "Desktop client" : "Cliente Desktop", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Mostrar administrador do usuário", "Send email to new user" : "Enviar um email para o novo usuário", "Show email address" : "Mostrar o endereço de email", - "Username" : "Nome de Usuário", "E-Mail" : "E-Mail", "Create" : "Criar", "Admin Recovery Password" : "Recuperação da Senha do Administrador", diff --git a/settings/l10n/pt_BR.json b/settings/l10n/pt_BR.json index 72f1be20054ab..249a3e29c076c 100644 --- a/settings/l10n/pt_BR.json +++ b/settings/l10n/pt_BR.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "A senha do aplicativo é um código de acesso que dá ao aplicativo ou dispositivo permissões para acessar sua conta %s.", "App name" : "Nome do aplicativo", "Create new app password" : "Criar uma nova senha do aplicativo", + "Username" : "Nome de Usuário", "Done" : "Concluída", "Get the apps to sync your files" : "Obtenha apps para sincronizar seus arquivos", "Desktop client" : "Cliente Desktop", @@ -290,7 +291,6 @@ "Show user backend" : "Mostrar administrador do usuário", "Send email to new user" : "Enviar um email para o novo usuário", "Show email address" : "Mostrar o endereço de email", - "Username" : "Nome de Usuário", "E-Mail" : "E-Mail", "Create" : "Criar", "Admin Recovery Password" : "Recuperação da Senha do Administrador", diff --git a/settings/l10n/pt_PT.js b/settings/l10n/pt_PT.js index bfadac2bc3f5f..f0c707c132820 100644 --- a/settings/l10n/pt_PT.js +++ b/settings/l10n/pt_PT.js @@ -273,6 +273,7 @@ OC.L10N.register( "Browser" : "Navegador", "Most recent activity" : "Atividade mais recente", "Name" : "Nome", + "Username" : "Nome de utilizador", "Done" : "Concluído", "Get the apps to sync your files" : "Obtenha as aplicações para sincronizar os seus ficheiros", "Desktop client" : "Cliente Desktop", @@ -286,7 +287,6 @@ OC.L10N.register( "Show user backend" : "Mostrar interface do utilizador", "Send email to new user" : "Enviar email ao novo utilizador", "Show email address" : "Mostrar endereço de email", - "Username" : "Nome de utilizador", "E-Mail" : "Correio Eletrónico", "Create" : "Criar", "Admin Recovery Password" : "Recuperação da Palavra-passe de Administrador", diff --git a/settings/l10n/pt_PT.json b/settings/l10n/pt_PT.json index cd934850e6954..6d0344bdbb616 100644 --- a/settings/l10n/pt_PT.json +++ b/settings/l10n/pt_PT.json @@ -271,6 +271,7 @@ "Browser" : "Navegador", "Most recent activity" : "Atividade mais recente", "Name" : "Nome", + "Username" : "Nome de utilizador", "Done" : "Concluído", "Get the apps to sync your files" : "Obtenha as aplicações para sincronizar os seus ficheiros", "Desktop client" : "Cliente Desktop", @@ -284,7 +285,6 @@ "Show user backend" : "Mostrar interface do utilizador", "Send email to new user" : "Enviar email ao novo utilizador", "Show email address" : "Mostrar endereço de email", - "Username" : "Nome de utilizador", "E-Mail" : "Correio Eletrónico", "Create" : "Criar", "Admin Recovery Password" : "Recuperação da Palavra-passe de Administrador", diff --git a/settings/l10n/ro.js b/settings/l10n/ro.js index d0a0b107d0a42..72846229056e2 100644 --- a/settings/l10n/ro.js +++ b/settings/l10n/ro.js @@ -199,11 +199,11 @@ OC.L10N.register( "Help translate" : "Ajută la traducere", "Most recent activity" : "Cea mai recentă activitate", "Name" : "Nume", + "Username" : "Nume utilizator", "Get the apps to sync your files" : "Ia acum aplicatia pentru sincronizarea fisierelor ", "Desktop client" : "Client Desktop", "Android app" : "Aplicatie Android", "iOS app" : "Aplicație iOS", - "Username" : "Nume utilizator", "E-Mail" : "Email", "Create" : "Crează", "Admin Recovery Password" : "Parolă de recuperare a Administratorului", diff --git a/settings/l10n/ro.json b/settings/l10n/ro.json index 4f3a30ab5c328..2ed3793dce0d6 100644 --- a/settings/l10n/ro.json +++ b/settings/l10n/ro.json @@ -197,11 +197,11 @@ "Help translate" : "Ajută la traducere", "Most recent activity" : "Cea mai recentă activitate", "Name" : "Nume", + "Username" : "Nume utilizator", "Get the apps to sync your files" : "Ia acum aplicatia pentru sincronizarea fisierelor ", "Desktop client" : "Client Desktop", "Android app" : "Aplicatie Android", "iOS app" : "Aplicație iOS", - "Username" : "Nume utilizator", "E-Mail" : "Email", "Create" : "Crează", "Admin Recovery Password" : "Parolă de recuperare a Administratorului", diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js index d4c952f7bd153..824f6f741722a 100644 --- a/settings/l10n/ru.js +++ b/settings/l10n/ru.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Пароль приложения представляет собой код доступа, который дает приложению или устройству разрешения на доступ к вашему аккаунту %s.", "App name" : "Название приложения", "Create new app password" : "Создать новый пароль для приложения", + "Username" : "Имя пользователя", "Done" : "Выполнено", "Get the apps to sync your files" : "Получить приложения для синхронизации ваших файлов", "Desktop client" : "Клиент для ПК", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Показать механизм учёта пользователей", "Send email to new user" : "Отправлять письмо новому пользователю", "Show email address" : "Показывать адрес электронной почты", - "Username" : "Имя пользователя", "E-Mail" : "Почта", "Create" : "Создать", "Admin Recovery Password" : "Пароль административного восстановления", diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json index 819a852658cf2..7a84ef3547541 100644 --- a/settings/l10n/ru.json +++ b/settings/l10n/ru.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Пароль приложения представляет собой код доступа, который дает приложению или устройству разрешения на доступ к вашему аккаунту %s.", "App name" : "Название приложения", "Create new app password" : "Создать новый пароль для приложения", + "Username" : "Имя пользователя", "Done" : "Выполнено", "Get the apps to sync your files" : "Получить приложения для синхронизации ваших файлов", "Desktop client" : "Клиент для ПК", @@ -290,7 +291,6 @@ "Show user backend" : "Показать механизм учёта пользователей", "Send email to new user" : "Отправлять письмо новому пользователю", "Show email address" : "Показывать адрес электронной почты", - "Username" : "Имя пользователя", "E-Mail" : "Почта", "Create" : "Создать", "Admin Recovery Password" : "Пароль административного восстановления", diff --git a/settings/l10n/sk_SK.js b/settings/l10n/sk_SK.js index 4ca631bb8b6f5..c249801c02c6d 100644 --- a/settings/l10n/sk_SK.js +++ b/settings/l10n/sk_SK.js @@ -214,6 +214,7 @@ OC.L10N.register( "Language" : "Jazyk", "Help translate" : "Pomôcť s prekladom", "Name" : "Názov", + "Username" : "Používateľské meno", "Done" : "Hotovo", "Get the apps to sync your files" : "Získať aplikácie na synchronizáciu vašich súborov", "Desktop client" : "Desktopový klient", @@ -227,7 +228,6 @@ OC.L10N.register( "Show user backend" : "Zobraziť backend používateľa", "Send email to new user" : "Odoslať email novému používateľovi", "Show email address" : "Zobraziť emailovú adresu", - "Username" : "Používateľské meno", "E-Mail" : "email", "Create" : "Vytvoriť", "Admin Recovery Password" : "Obnovenie hesla administrátora", diff --git a/settings/l10n/sk_SK.json b/settings/l10n/sk_SK.json index fbb0a5fe24f13..383795d6f3bd6 100644 --- a/settings/l10n/sk_SK.json +++ b/settings/l10n/sk_SK.json @@ -212,6 +212,7 @@ "Language" : "Jazyk", "Help translate" : "Pomôcť s prekladom", "Name" : "Názov", + "Username" : "Používateľské meno", "Done" : "Hotovo", "Get the apps to sync your files" : "Získať aplikácie na synchronizáciu vašich súborov", "Desktop client" : "Desktopový klient", @@ -225,7 +226,6 @@ "Show user backend" : "Zobraziť backend používateľa", "Send email to new user" : "Odoslať email novému používateľovi", "Show email address" : "Zobraziť emailovú adresu", - "Username" : "Používateľské meno", "E-Mail" : "email", "Create" : "Vytvoriť", "Admin Recovery Password" : "Obnovenie hesla administrátora", diff --git a/settings/l10n/sl.js b/settings/l10n/sl.js index f75df25d7fe67..fb5bacf721ee1 100644 --- a/settings/l10n/sl.js +++ b/settings/l10n/sl.js @@ -236,6 +236,7 @@ OC.L10N.register( "Browser" : "Brskalnik", "Most recent activity" : "Zadnja dejavnost", "Name" : "Ime", + "Username" : "Uporabniško ime", "Done" : "Končano", "Get the apps to sync your files" : "Pridobi programe za usklajevanje datotek", "Desktop client" : "Namizni odjemalec", @@ -249,7 +250,6 @@ OC.L10N.register( "Show user backend" : "Pokaži ozadnji program", "Send email to new user" : "Pošlji sporočilo novemu uporabniku", "Show email address" : "Pokaži naslov elektronske pošte", - "Username" : "Uporabniško ime", "E-Mail" : "Elektronska pošta", "Create" : "Ustvari", "Admin Recovery Password" : "Obnovitev skrbniškega gesla", diff --git a/settings/l10n/sl.json b/settings/l10n/sl.json index b7eb34f46f3fc..495206d568e32 100644 --- a/settings/l10n/sl.json +++ b/settings/l10n/sl.json @@ -234,6 +234,7 @@ "Browser" : "Brskalnik", "Most recent activity" : "Zadnja dejavnost", "Name" : "Ime", + "Username" : "Uporabniško ime", "Done" : "Končano", "Get the apps to sync your files" : "Pridobi programe za usklajevanje datotek", "Desktop client" : "Namizni odjemalec", @@ -247,7 +248,6 @@ "Show user backend" : "Pokaži ozadnji program", "Send email to new user" : "Pošlji sporočilo novemu uporabniku", "Show email address" : "Pokaži naslov elektronske pošte", - "Username" : "Uporabniško ime", "E-Mail" : "Elektronska pošta", "Create" : "Ustvari", "Admin Recovery Password" : "Obnovitev skrbniškega gesla", diff --git a/settings/l10n/sq.js b/settings/l10n/sq.js index dc949a0672613..f2e96691e23ed 100644 --- a/settings/l10n/sq.js +++ b/settings/l10n/sq.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Fjalëkalimet e aplikacioneve janë kodkalime që u japin leje një aplikacioni ose pajisjeje të hyjnë në llogarinë tuaj %s.", "App name" : "Emër aplikacioni", "Create new app password" : "Krijoni fjalëkalim aplikacioni të ri", + "Username" : "Emër përdoruesi", "Done" : "U bë", "Get the apps to sync your files" : "Merrni aplikacionet për njëkohësim të kartelave tuaja", "Desktop client" : "Klient desktopi", @@ -292,7 +293,6 @@ OC.L10N.register( "Show user backend" : "Shfaq programin klient të përdoruesit", "Send email to new user" : "Dërgo email përdoruesi të ri", "Show email address" : "Shfaq adresë email", - "Username" : "Emër përdoruesi", "E-Mail" : "Email", "Create" : "Krijoje", "Admin Recovery Password" : "Fjalëkalim Rikthimesh Nga Përgjegjësi", diff --git a/settings/l10n/sq.json b/settings/l10n/sq.json index bc625b6d67f26..812a3f5dc1309 100644 --- a/settings/l10n/sq.json +++ b/settings/l10n/sq.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Fjalëkalimet e aplikacioneve janë kodkalime që u japin leje një aplikacioni ose pajisjeje të hyjnë në llogarinë tuaj %s.", "App name" : "Emër aplikacioni", "Create new app password" : "Krijoni fjalëkalim aplikacioni të ri", + "Username" : "Emër përdoruesi", "Done" : "U bë", "Get the apps to sync your files" : "Merrni aplikacionet për njëkohësim të kartelave tuaja", "Desktop client" : "Klient desktopi", @@ -290,7 +291,6 @@ "Show user backend" : "Shfaq programin klient të përdoruesit", "Send email to new user" : "Dërgo email përdoruesi të ri", "Show email address" : "Shfaq adresë email", - "Username" : "Emër përdoruesi", "E-Mail" : "Email", "Create" : "Krijoje", "Admin Recovery Password" : "Fjalëkalim Rikthimesh Nga Përgjegjësi", diff --git a/settings/l10n/sr.js b/settings/l10n/sr.js index 5b77f607971b7..12fd48962be1a 100644 --- a/settings/l10n/sr.js +++ b/settings/l10n/sr.js @@ -223,6 +223,7 @@ OC.L10N.register( "Language" : "Језик", "Help translate" : " Помозите у превођењу", "Name" : "назив", + "Username" : "Корисничко име", "Done" : "Завршено", "Get the apps to sync your files" : "Преузмите апликације ради синхронизовања ваших фајлова", "Desktop client" : "Клијент за рачунар", @@ -236,7 +237,6 @@ OC.L10N.register( "Show user backend" : "Прикажи позадину за кориснике", "Send email to new user" : "Пошаљи е-пошту новом кориснику", "Show email address" : "Прикажи е-адресу", - "Username" : "Корисничко име", "E-Mail" : "Е-пошта", "Create" : "Направи", "Admin Recovery Password" : "Администраторска лозинка за опоравак", diff --git a/settings/l10n/sr.json b/settings/l10n/sr.json index 77513de8facf1..b47ec180dd77d 100644 --- a/settings/l10n/sr.json +++ b/settings/l10n/sr.json @@ -221,6 +221,7 @@ "Language" : "Језик", "Help translate" : " Помозите у превођењу", "Name" : "назив", + "Username" : "Корисничко име", "Done" : "Завршено", "Get the apps to sync your files" : "Преузмите апликације ради синхронизовања ваших фајлова", "Desktop client" : "Клијент за рачунар", @@ -234,7 +235,6 @@ "Show user backend" : "Прикажи позадину за кориснике", "Send email to new user" : "Пошаљи е-пошту новом кориснику", "Show email address" : "Прикажи е-адресу", - "Username" : "Корисничко име", "E-Mail" : "Е-пошта", "Create" : "Направи", "Admin Recovery Password" : "Администраторска лозинка за опоравак", diff --git a/settings/l10n/sr@latin.js b/settings/l10n/sr@latin.js index 148b1580597b3..5693fbf995dea 100644 --- a/settings/l10n/sr@latin.js +++ b/settings/l10n/sr@latin.js @@ -27,11 +27,11 @@ OC.L10N.register( "Change password" : "Izmeni lozinku", "Language" : "Jezik", "Name" : "naziv", + "Username" : "Korisničko ime", "Get the apps to sync your files" : "Preuzmite aplikacije za sinhronizaciju Vaših fajlova", "Desktop client" : "Desktop klijent", "Android app" : "Android aplikacija", "iOS app" : "iOS aplikacija", - "Username" : "Korisničko ime", "Create" : "Napravi", "Group" : "Grupa", "Other" : "Drugo" diff --git a/settings/l10n/sr@latin.json b/settings/l10n/sr@latin.json index c328b49d9b406..331191af2c536 100644 --- a/settings/l10n/sr@latin.json +++ b/settings/l10n/sr@latin.json @@ -25,11 +25,11 @@ "Change password" : "Izmeni lozinku", "Language" : "Jezik", "Name" : "naziv", + "Username" : "Korisničko ime", "Get the apps to sync your files" : "Preuzmite aplikacije za sinhronizaciju Vaših fajlova", "Desktop client" : "Desktop klijent", "Android app" : "Android aplikacija", "iOS app" : "iOS aplikacija", - "Username" : "Korisničko ime", "Create" : "Napravi", "Group" : "Grupa", "Other" : "Drugo" diff --git a/settings/l10n/sv.js b/settings/l10n/sv.js index 05b24bb4c756b..82223adf66240 100644 --- a/settings/l10n/sv.js +++ b/settings/l10n/sv.js @@ -274,6 +274,7 @@ OC.L10N.register( "Browser" : "Webbläsare", "Most recent activity" : "Senaste aktivitet", "Name" : "Namn", + "Username" : "Användarnamn", "Done" : "Färdig", "Get the apps to sync your files" : "Skaffa apparna för att synkronisera dina filer", "Desktop client" : "Skrivbordsklient", @@ -287,7 +288,6 @@ OC.L10N.register( "Show user backend" : "Visa användar-backend", "Send email to new user" : "Skicka e-post till ny användare", "Show email address" : "Visa e-postadress", - "Username" : "Användarnamn", "E-Mail" : "E-post", "Create" : "Skapa", "Admin Recovery Password" : "Admin-återställningslösenord", diff --git a/settings/l10n/sv.json b/settings/l10n/sv.json index d8e9422eeecb2..5e4faebb3cc25 100644 --- a/settings/l10n/sv.json +++ b/settings/l10n/sv.json @@ -272,6 +272,7 @@ "Browser" : "Webbläsare", "Most recent activity" : "Senaste aktivitet", "Name" : "Namn", + "Username" : "Användarnamn", "Done" : "Färdig", "Get the apps to sync your files" : "Skaffa apparna för att synkronisera dina filer", "Desktop client" : "Skrivbordsklient", @@ -285,7 +286,6 @@ "Show user backend" : "Visa användar-backend", "Send email to new user" : "Skicka e-post till ny användare", "Show email address" : "Visa e-postadress", - "Username" : "Användarnamn", "E-Mail" : "E-post", "Create" : "Skapa", "Admin Recovery Password" : "Admin-återställningslösenord", diff --git a/settings/l10n/th_TH.js b/settings/l10n/th_TH.js index b8517d661b5e9..b205728a30f39 100644 --- a/settings/l10n/th_TH.js +++ b/settings/l10n/th_TH.js @@ -258,6 +258,7 @@ OC.L10N.register( "Language" : "ภาษา", "Help translate" : "มาช่วยกันแปลสิ!", "Name" : "ชื่อ", + "Username" : "ชื่อผู้ใช้งาน", "Done" : "เสร็จสิ้น", "Get the apps to sync your files" : "ใช้แอพพลิเคชันในการประสานไฟล์ของคุณ", "Desktop client" : "เดสก์ทอปผู้ใช้", @@ -271,7 +272,6 @@ OC.L10N.register( "Show user backend" : "แสดงแบ็กเอนด์ของผู้ใช้", "Send email to new user" : "ส่งอีเมลไปยังผู้ใช้ใหม่", "Show email address" : "แสดงที่อยู่อีเมล", - "Username" : "ชื่อผู้ใช้งาน", "E-Mail" : "อีเมล", "Create" : "สร้าง", "Admin Recovery Password" : "กู้คืนรหัสผ่านดูแลระบบ", diff --git a/settings/l10n/th_TH.json b/settings/l10n/th_TH.json index 8d568dfecbc77..ab451fbcb4c3c 100644 --- a/settings/l10n/th_TH.json +++ b/settings/l10n/th_TH.json @@ -256,6 +256,7 @@ "Language" : "ภาษา", "Help translate" : "มาช่วยกันแปลสิ!", "Name" : "ชื่อ", + "Username" : "ชื่อผู้ใช้งาน", "Done" : "เสร็จสิ้น", "Get the apps to sync your files" : "ใช้แอพพลิเคชันในการประสานไฟล์ของคุณ", "Desktop client" : "เดสก์ทอปผู้ใช้", @@ -269,7 +270,6 @@ "Show user backend" : "แสดงแบ็กเอนด์ของผู้ใช้", "Send email to new user" : "ส่งอีเมลไปยังผู้ใช้ใหม่", "Show email address" : "แสดงที่อยู่อีเมล", - "Username" : "ชื่อผู้ใช้งาน", "E-Mail" : "อีเมล", "Create" : "สร้าง", "Admin Recovery Password" : "กู้คืนรหัสผ่านดูแลระบบ", diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js index 9a2962ad20963..38a06e23850a4 100644 --- a/settings/l10n/tr.js +++ b/settings/l10n/tr.js @@ -263,6 +263,7 @@ OC.L10N.register( "Language" : "Dil", "Help translate" : "Çevirilere yardım edin", "Name" : "Ad", + "Username" : "Kullanıcı Adı", "Done" : "Bitti", "Get the apps to sync your files" : "Dosyalarınızı eşitlemek için uygulamaları indirin", "Desktop client" : "Masaüstü istemcisi", @@ -276,7 +277,6 @@ OC.L10N.register( "Show user backend" : "Kullanıcı arka ucunu göster", "Send email to new user" : "Yeni kullanıcıya e-posta gönder", "Show email address" : "E-posta adresini göster", - "Username" : "Kullanıcı Adı", "E-Mail" : "E-Posta", "Create" : "Oluştur", "Admin Recovery Password" : "Yönetici Kurtarma Parolası", diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json index 4e3c867c7f499..07b7584bd4260 100644 --- a/settings/l10n/tr.json +++ b/settings/l10n/tr.json @@ -261,6 +261,7 @@ "Language" : "Dil", "Help translate" : "Çevirilere yardım edin", "Name" : "Ad", + "Username" : "Kullanıcı Adı", "Done" : "Bitti", "Get the apps to sync your files" : "Dosyalarınızı eşitlemek için uygulamaları indirin", "Desktop client" : "Masaüstü istemcisi", @@ -274,7 +275,6 @@ "Show user backend" : "Kullanıcı arka ucunu göster", "Send email to new user" : "Yeni kullanıcıya e-posta gönder", "Show email address" : "E-posta adresini göster", - "Username" : "Kullanıcı Adı", "E-Mail" : "E-Posta", "Create" : "Oluştur", "Admin Recovery Password" : "Yönetici Kurtarma Parolası", diff --git a/settings/l10n/uk.js b/settings/l10n/uk.js index a1afbc55f45ea..f7ab8f883616a 100644 --- a/settings/l10n/uk.js +++ b/settings/l10n/uk.js @@ -227,6 +227,7 @@ OC.L10N.register( "Language" : "Мова", "Help translate" : "Допомогти з перекладом", "Name" : "Ім’я", + "Username" : "Ім'я користувача", "Done" : "Готово", "Get the apps to sync your files" : "Отримати додатки для синхронізації ваших файлів", "Desktop client" : "Клієнт для ПК", @@ -240,7 +241,6 @@ OC.L10N.register( "Show user backend" : "Показати користувача", "Send email to new user" : "Надіслати email новому користувачу", "Show email address" : "Показати адресу електронної пошти", - "Username" : "Ім'я користувача", "E-Mail" : "Адреса електронної пошти", "Create" : "Створити", "Admin Recovery Password" : "Пароль адміністратора для відновлення", diff --git a/settings/l10n/uk.json b/settings/l10n/uk.json index 4ab44f9623a48..a1ce577740c5f 100644 --- a/settings/l10n/uk.json +++ b/settings/l10n/uk.json @@ -225,6 +225,7 @@ "Language" : "Мова", "Help translate" : "Допомогти з перекладом", "Name" : "Ім’я", + "Username" : "Ім'я користувача", "Done" : "Готово", "Get the apps to sync your files" : "Отримати додатки для синхронізації ваших файлів", "Desktop client" : "Клієнт для ПК", @@ -238,7 +239,6 @@ "Show user backend" : "Показати користувача", "Send email to new user" : "Надіслати email новому користувачу", "Show email address" : "Показати адресу електронної пошти", - "Username" : "Ім'я користувача", "E-Mail" : "Адреса електронної пошти", "Create" : "Створити", "Admin Recovery Password" : "Пароль адміністратора для відновлення", diff --git a/settings/l10n/vi.js b/settings/l10n/vi.js index f2decd23b0b2a..55ace0c8a40b1 100644 --- a/settings/l10n/vi.js +++ b/settings/l10n/vi.js @@ -59,9 +59,9 @@ OC.L10N.register( "Language" : "Ngôn ngữ", "Help translate" : "Hỗ trợ dịch thuật", "Name" : "Tên", + "Username" : "Tên đăng nhập", "Get the apps to sync your files" : "Nhận ứng dụng để đồng bộ file của bạn", "Show First Run Wizard again" : "Hiện lại việc chạy đồ thuật khởi đầu", - "Username" : "Tên đăng nhập", "Create" : "Tạo", "Group" : "N", "Default Quota" : "Hạn ngạch mặt định", diff --git a/settings/l10n/vi.json b/settings/l10n/vi.json index bd843122822f5..8eb4b306a66d2 100644 --- a/settings/l10n/vi.json +++ b/settings/l10n/vi.json @@ -57,9 +57,9 @@ "Language" : "Ngôn ngữ", "Help translate" : "Hỗ trợ dịch thuật", "Name" : "Tên", + "Username" : "Tên đăng nhập", "Get the apps to sync your files" : "Nhận ứng dụng để đồng bộ file của bạn", "Show First Run Wizard again" : "Hiện lại việc chạy đồ thuật khởi đầu", - "Username" : "Tên đăng nhập", "Create" : "Tạo", "Group" : "N", "Default Quota" : "Hạn ngạch mặt định", diff --git a/settings/l10n/zh_CN.js b/settings/l10n/zh_CN.js index 41cb2e7a38b9e..df0a5873876a8 100644 --- a/settings/l10n/zh_CN.js +++ b/settings/l10n/zh_CN.js @@ -254,6 +254,7 @@ OC.L10N.register( "Language" : "语言", "Help translate" : "帮助翻译", "Name" : "名称", + "Username" : "用户名", "Get the apps to sync your files" : "安装应用进行文件同步", "Desktop client" : "桌面客户端", "Android app" : "Android 应用", @@ -266,7 +267,6 @@ OC.L10N.register( "Show user backend" : "显示用户后端", "Send email to new user" : "发送电子邮件给新用户", "Show email address" : "显示邮件地址", - "Username" : "用户名", "E-Mail" : "E-Mail", "Create" : "创建", "Admin Recovery Password" : "管理恢复密码", diff --git a/settings/l10n/zh_CN.json b/settings/l10n/zh_CN.json index 64b09cfbd5928..1e56a61f06bd7 100644 --- a/settings/l10n/zh_CN.json +++ b/settings/l10n/zh_CN.json @@ -252,6 +252,7 @@ "Language" : "语言", "Help translate" : "帮助翻译", "Name" : "名称", + "Username" : "用户名", "Get the apps to sync your files" : "安装应用进行文件同步", "Desktop client" : "桌面客户端", "Android app" : "Android 应用", @@ -264,7 +265,6 @@ "Show user backend" : "显示用户后端", "Send email to new user" : "发送电子邮件给新用户", "Show email address" : "显示邮件地址", - "Username" : "用户名", "E-Mail" : "E-Mail", "Create" : "创建", "Admin Recovery Password" : "管理恢复密码", diff --git a/settings/l10n/zh_HK.js b/settings/l10n/zh_HK.js index 6f1cd57b7925e..fbc7a93eb1d09 100644 --- a/settings/l10n/zh_HK.js +++ b/settings/l10n/zh_HK.js @@ -46,9 +46,9 @@ OC.L10N.register( "Language" : "語言", "Help translate" : "幫忙翻譯", "Name" : "名稱", + "Username" : "用戶名稱", "Android app" : "Android 應用程式", "iOS app" : "iOS 應用程式", - "Username" : "用戶名稱", "Create" : "新增", "Group" : "群組", "Everyone" : "所有人", diff --git a/settings/l10n/zh_HK.json b/settings/l10n/zh_HK.json index ac76df209b390..7ada073d1ff1c 100644 --- a/settings/l10n/zh_HK.json +++ b/settings/l10n/zh_HK.json @@ -44,9 +44,9 @@ "Language" : "語言", "Help translate" : "幫忙翻譯", "Name" : "名稱", + "Username" : "用戶名稱", "Android app" : "Android 應用程式", "iOS app" : "iOS 應用程式", - "Username" : "用戶名稱", "Create" : "新增", "Group" : "群組", "Everyone" : "所有人", diff --git a/settings/l10n/zh_TW.js b/settings/l10n/zh_TW.js index 09c4dcd369b50..83d3b25409367 100644 --- a/settings/l10n/zh_TW.js +++ b/settings/l10n/zh_TW.js @@ -248,6 +248,7 @@ OC.L10N.register( "Language" : "語言", "Help translate" : "幫助翻譯", "Name" : "名稱", + "Username" : "使用者名稱", "Get the apps to sync your files" : "下載應用程式來同步您的檔案", "Desktop client" : "桌面客戶端", "Android app" : "Android 應用程式", @@ -260,7 +261,6 @@ OC.L10N.register( "Show user backend" : "顯示用戶後台", "Send email to new user" : "寄送郵件給新用戶", "Show email address" : "顯示電子郵件信箱", - "Username" : "使用者名稱", "E-Mail" : "電子郵件", "Create" : "建立", "Admin Recovery Password" : "管理者復原密碼", diff --git a/settings/l10n/zh_TW.json b/settings/l10n/zh_TW.json index 35f5ac52190b6..f48f802c7d6ed 100644 --- a/settings/l10n/zh_TW.json +++ b/settings/l10n/zh_TW.json @@ -246,6 +246,7 @@ "Language" : "語言", "Help translate" : "幫助翻譯", "Name" : "名稱", + "Username" : "使用者名稱", "Get the apps to sync your files" : "下載應用程式來同步您的檔案", "Desktop client" : "桌面客戶端", "Android app" : "Android 應用程式", @@ -258,7 +259,6 @@ "Show user backend" : "顯示用戶後台", "Send email to new user" : "寄送郵件給新用戶", "Show email address" : "顯示電子郵件信箱", - "Username" : "使用者名稱", "E-Mail" : "電子郵件", "Create" : "建立", "Admin Recovery Password" : "管理者復原密碼", From 6a1d9d0c32d29d858f178b453d1ed35aa770617c Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 28 Jun 2016 12:09:58 +0200 Subject: [PATCH 38/81] Hide revert button when no permission to revert --- apps/files_versions/js/versionstabview.js | 6 +++ apps/files_versions/lib/Storage.php | 8 ++++ apps/files_versions/tests/VersioningTest.php | 38 ++++++++++++++++++- .../tests/js/versionstabviewSpec.js | 28 +++++++++++++- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/apps/files_versions/js/versionstabview.js b/apps/files_versions/js/versionstabview.js index 0e17fff466a17..b9ccf03c3e29b 100644 --- a/apps/files_versions/js/versionstabview.js +++ b/apps/files_versions/js/versionstabview.js @@ -15,7 +15,9 @@ '' + '{{relativeTimestamp}}' + '' + + '{{#canRevert}}' + '' + + '{{/canRevert}}' + ''; var TEMPLATE = @@ -109,6 +111,9 @@ }, error: function() { + fileInfoModel.trigger('busy', fileInfoModel, false); + self.$el.find('.versions').removeClass('hidden'); + self._toggleLoading(false); OC.Notification.showTemporary( t('files_version', 'Failed to revert {file} to revision {timestamp}.', { file: versionModel.getFullPath(), @@ -183,6 +188,7 @@ revertIconUrl: OC.imagePath('core', 'actions/history'), previewUrl: version.getPreviewUrl(), revertLabel: t('files_versions', 'Restore'), + canRevert: (this.collection.getFileInfo().get('permissions') & OC.PERMISSION_UPDATE) !== 0 }, version.attributes); }, diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index 93f8b848ce8c5..6345d4c303bc1 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -320,8 +320,16 @@ public static function rollback($file, $revision) { // add expected leading slash $file = '/' . ltrim($file, '/'); list($uid, $filename) = self::getUidAndFilename($file); + if ($uid === null || trim($filename, '/') === '') { + return false; + } $users_view = new View('/'.$uid); $files_view = new View('/'. User::getUser().'/files'); + + if (!$files_view->isUpdatable($filename)) { + return false; + } + $versionCreated = false; //first create a new version diff --git a/apps/files_versions/tests/VersioningTest.php b/apps/files_versions/tests/VersioningTest.php index 2a65682f0fefd..832f7bcc66fa7 100644 --- a/apps/files_versions/tests/VersioningTest.php +++ b/apps/files_versions/tests/VersioningTest.php @@ -625,6 +625,40 @@ public function testRestoreCrossStorage() { $this->doTestRestore(); } + public function testRestoreNoPermission() { + $this->loginAsUser(self::TEST_VERSIONS_USER); + + $userHome = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER); + $node = $userHome->newFolder('folder'); + $file = $node->newFile('test.txt'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedBy(self::TEST_VERSIONS_USER) + ->setSharedWith(self::TEST_VERSIONS_USER2) + ->setPermissions(\OCP\Constants::PERMISSION_READ); + $share = \OC::$server->getShareManager()->createShare($share); + + $versions = $this->createAndCheckVersions( + \OC\Files\Filesystem::getView(), + 'folder/test.txt' + ); + + $file->putContent('test file'); + + $this->loginAsUser(self::TEST_VERSIONS_USER2); + + $firstVersion = current($versions); + + $this->assertFalse(\OCA\Files_Versions\Storage::rollback('folder/test.txt', $firstVersion['version']), 'Revert did not happen'); + + $this->loginAsUser(self::TEST_VERSIONS_USER); + + \OC::$server->getShareManager()->deleteShare($share); + $this->assertEquals('test file', $file->getContent(), 'File content has not changed'); + } + /** * @param string $hookName name of hook called * @param string $params variable to receive parameters provided by hook @@ -685,7 +719,7 @@ private function doTestRestore() { $params = array(); $this->connectMockHooks('rollback', $params); - \OCA\Files_Versions\Storage::rollback('sub/test.txt', $t2); + $this->assertTrue(\OCA\Files_Versions\Storage::rollback('sub/test.txt', $t2)); $expectedParams = array( 'path' => '/sub/test.txt', ); @@ -829,6 +863,8 @@ private function createAndCheckVersions(\OC\Files\View $view, $path) { // note: we cannot predict how many versions are created due to // test run timing $this->assertGreaterThan(0, count($versions)); + + return $versions; } /** diff --git a/apps/files_versions/tests/js/versionstabviewSpec.js b/apps/files_versions/tests/js/versionstabviewSpec.js index 306dd66be2ac3..94285c93abaf7 100644 --- a/apps/files_versions/tests/js/versionstabviewSpec.js +++ b/apps/files_versions/tests/js/versionstabviewSpec.js @@ -39,7 +39,8 @@ describe('OCA.Versions.VersionsTabView', function() { fetchStub = sinon.stub(VersionCollection.prototype, 'fetch'); fileInfoModel = new OCA.Files.FileInfoModel({ id: 123, - name: 'test.txt' + name: 'test.txt', + permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE }); tabView = new VersionsTabView(); tabView.render(); @@ -86,12 +87,37 @@ describe('OCA.Versions.VersionsTabView', function() { expect($item.find('.revertVersion').length).toEqual(1); expect($item.find('.preview').attr('src')).toEqual(version2.getPreviewUrl()); }); + + it('does not render revert button when no update permissions', function() { + + fileInfoModel.set('permissions', OC.PERMISSION_READ); + tabView.setFileInfo(fileInfoModel); + tabView.collection.set(testVersions); + + var version1 = testVersions[0]; + var version2 = testVersions[1]; + var $versions = tabView.$el.find('.versions>li'); + expect($versions.length).toEqual(2); + var $item = $versions.eq(0); + expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl()); + expect($item.find('.versiondate').text()).toEqual('seconds ago'); + expect($item.find('.revertVersion').length).toEqual(0); + expect($item.find('.preview').attr('src')).toEqual(version1.getPreviewUrl()); + + $item = $versions.eq(1); + expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl()); + expect($item.find('.versiondate').text()).toEqual('2 days ago'); + expect($item.find('.revertVersion').length).toEqual(0); + expect($item.find('.preview').attr('src')).toEqual(version2.getPreviewUrl()); + }); }); describe('More versions', function() { var hasMoreResultsStub; beforeEach(function() { + tabView.setFileInfo(fileInfoModel); + fetchStub.reset(); tabView.collection.set(testVersions); hasMoreResultsStub = sinon.stub(VersionCollection.prototype, 'hasMoreResults'); }); From f3c75de95ad07cfbb9c1dfcd4be4b0e967f7b406 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 28 Jun 2016 16:11:06 +0200 Subject: [PATCH 39/81] get only vcard which match both the address book id and the vcard uri --- apps/dav/lib/CardDAV/CardDavBackend.php | 2 +- apps/dav/tests/unit/CardDAV/CardDavBackendTest.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 2ad9f4778c927..39f76a4b42065 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -848,7 +848,7 @@ public function getContact($addressBookId, $uri) { $query = $this->db->getQueryBuilder(); $query->select('*')->from($this->dbCardsTable) ->where($query->expr()->eq('uri', $query->createNamedParameter($uri))) - ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); + ->andWhere($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); $queryResult = $query->execute(); $contact = $queryResult->fetch(); $queryResult->closeCursor(); diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index 58a93befe681f..9845d2d6909d5 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -606,6 +606,11 @@ public function testGetContact() { $this->assertSame(5489543, (int)$result['lastmodified']); $this->assertSame('etag0', $result['etag']); $this->assertSame(120, (int)$result['size']); + + // this shouldn't return any result because 'uri1' is in address book 1 + // see https://github.com/nextcloud/server/issues/229 + $result = $this->backend->getContact(0, 'uri1'); + $this->assertEmpty($result); } public function testGetContactFail() { From 4574bc141fdc5daeb44a47de6080df9714336872 Mon Sep 17 00:00:00 2001 From: Vincent Chan Date: Tue, 28 Jun 2016 18:39:51 +0200 Subject: [PATCH 40/81] targets 3rdparty submodule from Nc instead of oC --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index bc2beee81adcc..ce19da40ee647 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "3rdparty"] path = 3rdparty - url = https://github.com/owncloud/3rdparty.git + url = https://github.com/nextcloud/3rdparty.git From e1c24e7c50ef4d229b85274e78d23e11abd49c9d Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Wed, 29 Jun 2016 05:52:18 -0400 Subject: [PATCH 41/81] [tx-robot] updated from transifex --- apps/comments/l10n/nl.js | 2 + apps/comments/l10n/nl.json | 2 + apps/comments/l10n/sl.js | 3 + apps/comments/l10n/sl.json | 3 + apps/files/l10n/fr.js | 8 ++ apps/files/l10n/fr.json | 8 ++ apps/files_external/l10n/sl.js | 1 + apps/files_external/l10n/sl.json | 1 + apps/files_sharing/l10n/ast.js | 1 + apps/files_sharing/l10n/ast.json | 1 + apps/updatenotification/l10n/sl.js | 3 +- apps/updatenotification/l10n/sl.json | 3 +- core/l10n/ast.js | 39 ++++++++ core/l10n/ast.json | 39 ++++++++ core/l10n/fr.js | 2 + core/l10n/fr.json | 2 + core/l10n/lb.js | 138 ++++++++++++++++++++++++++- core/l10n/lb.json | 138 ++++++++++++++++++++++++++- core/l10n/sl.js | 3 + core/l10n/sl.json | 3 + lib/l10n/hu_HU.js | 13 +++ lib/l10n/hu_HU.json | 13 +++ lib/l10n/sl.js | 2 + lib/l10n/sl.json | 2 + settings/l10n/cs_CZ.js | 1 + settings/l10n/cs_CZ.json | 1 + settings/l10n/de.js | 1 + settings/l10n/de.json | 1 + settings/l10n/fi_FI.js | 1 + settings/l10n/fi_FI.json | 1 + settings/l10n/fr.js | 8 ++ settings/l10n/fr.json | 8 ++ settings/l10n/he.js | 1 + settings/l10n/he.json | 1 + settings/l10n/it.js | 1 + settings/l10n/it.json | 1 + settings/l10n/nl.js | 4 + settings/l10n/nl.json | 4 + settings/l10n/ru.js | 1 + settings/l10n/ru.json | 1 + settings/l10n/sl.js | 14 +++ settings/l10n/sl.json | 14 +++ settings/l10n/sq.js | 1 + settings/l10n/sq.json | 1 + 44 files changed, 486 insertions(+), 10 deletions(-) diff --git a/apps/comments/l10n/nl.js b/apps/comments/l10n/nl.js index 01cfc7045369e..4ccce751303bf 100644 --- a/apps/comments/l10n/nl.js +++ b/apps/comments/l10n/nl.js @@ -12,6 +12,8 @@ OC.L10N.register( "More comments..." : "Meer reacties...", "Save" : "Opslaan", "Allowed characters {count} of {max}" : "{count} van de {max} toegestane tekens", + "Error occurred while retrieving comment with id {id}" : "Er trad een fout op bij het ophalen van reactie met id {id}", + "Error occurred while updating comment with id {id}" : "Er trad een fout op bij het bijwerken van reactie met id {id}", "{count} unread comments" : "{count} ongelezen reacties", "Comment" : "Reactie", "Comments for files (always listed in stream)" : "Reacties voor bestanden (altijd getoond in de stroom)", diff --git a/apps/comments/l10n/nl.json b/apps/comments/l10n/nl.json index 1bdb76aabd586..be26788962cbe 100644 --- a/apps/comments/l10n/nl.json +++ b/apps/comments/l10n/nl.json @@ -10,6 +10,8 @@ "More comments..." : "Meer reacties...", "Save" : "Opslaan", "Allowed characters {count} of {max}" : "{count} van de {max} toegestane tekens", + "Error occurred while retrieving comment with id {id}" : "Er trad een fout op bij het ophalen van reactie met id {id}", + "Error occurred while updating comment with id {id}" : "Er trad een fout op bij het bijwerken van reactie met id {id}", "{count} unread comments" : "{count} ongelezen reacties", "Comment" : "Reactie", "Comments for files (always listed in stream)" : "Reacties voor bestanden (altijd getoond in de stroom)", diff --git a/apps/comments/l10n/sl.js b/apps/comments/l10n/sl.js index 263522cf3e548..f6b66a634f084 100644 --- a/apps/comments/l10n/sl.js +++ b/apps/comments/l10n/sl.js @@ -12,6 +12,9 @@ OC.L10N.register( "More comments..." : "Več opomb ...", "Save" : "Shrani", "Allowed characters {count} of {max}" : "Dovoljeni znaki: {count} od {max}", + "Error occurred while retrieving comment with id {id}" : "Napaka se je zgodila med prenosom komentarja z oznako {id}", + "Error occurred while updating comment with id {id}" : "Napaka se je zgodila med posodabljanjem komentarja z oznako {id}", + "Error occurred while posting comment" : "Napaka se je zgodila med predajo komentarja", "{count} unread comments" : "{count} neprebranih opomb", "Comment" : "Opomba", "Comments for files (always listed in stream)" : "Opombe k datotekam (vedno pokaži)", diff --git a/apps/comments/l10n/sl.json b/apps/comments/l10n/sl.json index 8a52d03c8c369..5bf96f2773b4d 100644 --- a/apps/comments/l10n/sl.json +++ b/apps/comments/l10n/sl.json @@ -10,6 +10,9 @@ "More comments..." : "Več opomb ...", "Save" : "Shrani", "Allowed characters {count} of {max}" : "Dovoljeni znaki: {count} od {max}", + "Error occurred while retrieving comment with id {id}" : "Napaka se je zgodila med prenosom komentarja z oznako {id}", + "Error occurred while updating comment with id {id}" : "Napaka se je zgodila med posodabljanjem komentarja z oznako {id}", + "Error occurred while posting comment" : "Napaka se je zgodila med predajo komentarja", "{count} unread comments" : "{count} neprebranih opomb", "Comment" : "Opomba", "Comments for files (always listed in stream)" : "Opombe k datotekam (vedno pokaži)", diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js index b2d6662a9ce70..b09bea28607d3 100644 --- a/apps/files/l10n/fr.js +++ b/apps/files/l10n/fr.js @@ -33,7 +33,15 @@ OC.L10N.register( "Could not get result from server." : "Ne peut recevoir les résultats du serveur.", "Uploading..." : "Téléversement en cours…", "..." : "...", + "{hours}:{minutes}:{seconds} hour{plural_s} left" : "{hours}:{minutes}:{seconds} heure{plural_s} restante{plural_s}", + "{hours}:{minutes}h" : "{hours}:{minutes}h", + "{minutes}:{seconds} minute{plural_s} left" : "{minutes}:{seconds} minute{plural_s} restante{plural_s}", + "{minutes}:{seconds}m" : "{minutes}:{seconds}m", + "{seconds} second{plural_s} left" : "{seconds} seconde{plural_s} restante{plural_s}", + "{seconds}s" : "{seconds}s", + "Any moment now..." : "D'un instant à l'autre...", "Soon..." : "Bientôt...", + "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} sur {totalSize} ({bitrate})", "File upload is in progress. Leaving the page now will cancel the upload." : "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier.", "Actions" : "Actions", "Download" : "Télécharger", diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json index 780ef364b9fc3..882c40094df19 100644 --- a/apps/files/l10n/fr.json +++ b/apps/files/l10n/fr.json @@ -31,7 +31,15 @@ "Could not get result from server." : "Ne peut recevoir les résultats du serveur.", "Uploading..." : "Téléversement en cours…", "..." : "...", + "{hours}:{minutes}:{seconds} hour{plural_s} left" : "{hours}:{minutes}:{seconds} heure{plural_s} restante{plural_s}", + "{hours}:{minutes}h" : "{hours}:{minutes}h", + "{minutes}:{seconds} minute{plural_s} left" : "{minutes}:{seconds} minute{plural_s} restante{plural_s}", + "{minutes}:{seconds}m" : "{minutes}:{seconds}m", + "{seconds} second{plural_s} left" : "{seconds} seconde{plural_s} restante{plural_s}", + "{seconds}s" : "{seconds}s", + "Any moment now..." : "D'un instant à l'autre...", "Soon..." : "Bientôt...", + "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} sur {totalSize} ({bitrate})", "File upload is in progress. Leaving the page now will cancel the upload." : "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier.", "Actions" : "Actions", "Download" : "Télécharger", diff --git a/apps/files_external/l10n/sl.js b/apps/files_external/l10n/sl.js index 3de90f516e78d..4b8be72815550 100644 --- a/apps/files_external/l10n/sl.js +++ b/apps/files_external/l10n/sl.js @@ -18,6 +18,7 @@ OC.L10N.register( "Error generating key pair" : "Prišlo je do napake med ustvarjanjem para ključev", "All users. Type to select user or group." : "Vsi uporabniki. Skupino ali uporabnika je mogoče tudi izbrati.", "(group)" : "(skupina)", + "Compatibility with Mac NFD encoding (slow)" : "Usklajenost z Mac NFD šifriranjem (počasno)", "Admin defined" : "Skrbnik je določen", "Saved" : "Shranjeno", "Empty response from the server" : "S strežnika je prejet odziv brez vsebine.", diff --git a/apps/files_external/l10n/sl.json b/apps/files_external/l10n/sl.json index de512656d0c16..26648ce76dfe3 100644 --- a/apps/files_external/l10n/sl.json +++ b/apps/files_external/l10n/sl.json @@ -16,6 +16,7 @@ "Error generating key pair" : "Prišlo je do napake med ustvarjanjem para ključev", "All users. Type to select user or group." : "Vsi uporabniki. Skupino ali uporabnika je mogoče tudi izbrati.", "(group)" : "(skupina)", + "Compatibility with Mac NFD encoding (slow)" : "Usklajenost z Mac NFD šifriranjem (počasno)", "Admin defined" : "Skrbnik je določen", "Saved" : "Shranjeno", "Empty response from the server" : "S strežnika je prejet odziv brez vsebine.", diff --git a/apps/files_sharing/l10n/ast.js b/apps/files_sharing/l10n/ast.js index 2dea9485001a3..96e83dc54d424 100644 --- a/apps/files_sharing/l10n/ast.js +++ b/apps/files_sharing/l10n/ast.js @@ -13,6 +13,7 @@ OC.L10N.register( "Remote share password" : "Contraseña de compartición remota", "Cancel" : "Encaboxar", "Add remote share" : "Amestar compartición remota", + "No ownCloud installation (7 or higher) found at {remote}" : "Nun s'atopó nenguna instalación ownCloud (7 o cimera) en { } remotu", "Invalid ownCloud url" : "Url ownCloud inválida", "Shared by" : "Compartíos por", "Sharing" : "Compartiendo", diff --git a/apps/files_sharing/l10n/ast.json b/apps/files_sharing/l10n/ast.json index f06f63a44b7fa..78318f9a479c6 100644 --- a/apps/files_sharing/l10n/ast.json +++ b/apps/files_sharing/l10n/ast.json @@ -11,6 +11,7 @@ "Remote share password" : "Contraseña de compartición remota", "Cancel" : "Encaboxar", "Add remote share" : "Amestar compartición remota", + "No ownCloud installation (7 or higher) found at {remote}" : "Nun s'atopó nenguna instalación ownCloud (7 o cimera) en { } remotu", "Invalid ownCloud url" : "Url ownCloud inválida", "Shared by" : "Compartíos por", "Sharing" : "Compartiendo", diff --git a/apps/updatenotification/l10n/sl.js b/apps/updatenotification/l10n/sl.js index a59a58731fb4d..550f2055d228c 100644 --- a/apps/updatenotification/l10n/sl.js +++ b/apps/updatenotification/l10n/sl.js @@ -13,6 +13,7 @@ OC.L10N.register( "Checked on %s" : "Zadnjič preverjeno %s", "Update channel:" : "Posodobi kanal:", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Nadgradnja na višjo različico ali preizkusni kanal je vedno mogoča, ne pa tudi povrnitev na predhodno, bolj stabilno različico.", - "Notify members of the following groups about available updates:" : "Obvestite člane naslednjih skupin o posodobitvah, ki so na voljo:" + "Notify members of the following groups about available updates:" : "Obvestite člane naslednjih skupin o posodobitvah, ki so na voljo:", + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Na voljo so samo obvestila za posodobitev aplikacije, ker izbrani ownCloud posodobitveni kanal ne omogoča obveščanja." }, "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"); diff --git a/apps/updatenotification/l10n/sl.json b/apps/updatenotification/l10n/sl.json index c96c9666fb10e..c3575fcfacd7c 100644 --- a/apps/updatenotification/l10n/sl.json +++ b/apps/updatenotification/l10n/sl.json @@ -11,6 +11,7 @@ "Checked on %s" : "Zadnjič preverjeno %s", "Update channel:" : "Posodobi kanal:", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Nadgradnja na višjo različico ali preizkusni kanal je vedno mogoča, ne pa tudi povrnitev na predhodno, bolj stabilno različico.", - "Notify members of the following groups about available updates:" : "Obvestite člane naslednjih skupin o posodobitvah, ki so na voljo:" + "Notify members of the following groups about available updates:" : "Obvestite člane naslednjih skupin o posodobitvah, ki so na voljo:", + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Na voljo so samo obvestila za posodobitev aplikacije, ker izbrani ownCloud posodobitveni kanal ne omogoča obveščanja." },"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/ast.js b/core/l10n/ast.js index 9cbd176e5e526..ffb8fa94e2db4 100644 --- a/core/l10n/ast.js +++ b/core/l10n/ast.js @@ -1,13 +1,21 @@ OC.L10N.register( "core", { + "Please select a file." : "Por favor esbilla un ficheru.", + "File is too big" : "Ficheru ye demasiáu grande", + "Invalid file provided" : "el ficheru apurríu nun ye válidu", "No image or file provided" : "Nun s'especificó nenguna imaxe o ficheru", "Unknown filetype" : "Triba de ficheru desconocida", "Invalid image" : "Imaxe inválida", + "An error occurred. Please contact your admin." : "Hebo un fallu. Por favor, contauta col to alministrador", "No temporary profile picture available, try again" : "Nengún perfil d'imaxe temporal disponible, intentalo de nueves", "No crop data provided" : "Nun s'apurrió'l retayu de datos", + "No valid crop data provided" : "El retayu de datos apurríu nun ye válidu", + "Crop is not square" : "El retayu nun ye cuadráu", "Couldn't reset password because the token is invalid" : "Nun pudo reaniciase la contraseña porque'l token ye inválidu", + "Couldn't reset password because the token is expired" : "Nun pudo reaniciase la contraseña porque'l token ye inválidu", "Couldn't send reset email. Please make sure your username is correct." : "Nun pudo unviase'l corréu. Por favor, asegurate que'l to nome d'usuariu seya correutu", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Nun pudo unviase'l corréu porque nun hai direición de corréu pa esti nome d'usuariu. Por favor, contauta col alministrador.", "%s password reset" : "%s restablecer contraseña", "Couldn't send reset email. Please contact your administrator." : "Nun pudo unviase'l corréu de reaniciu. Por favor, contauta col alministrador.", "Error loading tags" : "Fallu cargando les etiquetes", @@ -18,12 +26,31 @@ OC.L10N.register( "Error favoriting" : "Fallu al marcar favoritos", "Error unfavoriting" : "Fallu al desmarcar favoritos", "Couldn't send mail to following users: %s " : "Nun pudo unviase'l corréu a los usuarios siguientes: %s", + "Preparing update" : "Preparando anovamientu", + "[%d / %d]: %s" : "[%d / %d]: %s", + "Repair warning: " : "Reparar avisu:", + "Repair error: " : "Reparar erru:", + "Please use the command line updater because automatic updating is disabled in the config.php." : "Por favor, usa l'actualización de llínea de comandos porque l'actualización automática ta deshabilitada nel config.php.", + "[%d / %d]: Checking table %s" : "[%d / %d]: Comprobando tabla %s", "Turned on maintenance mode" : "Activáu'l mou de caltenimientu", "Turned off maintenance mode" : "Apagáu'l mou de caltenimientu", + "Maintenance mode is kept active" : "La mou de caltenimientu caltiense activu", + "Updating database schema" : "Anovando esquema de base de datos", "Updated database" : "Base de datos anovada", + "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Comprobando si l'esquema de base de datos puede ser actualizáu (esto puede llevar tiempu abondo, dependiendo del tamañu la base de datos)", "Checked database schema update" : "Anovamientu del esquema de base de datos revisáu", + "Checking updates of apps" : "Comprobando anovamientos d'aplicaciones", + "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Comprobando si l'esquema de base de datos para %s puede ser actualizáu (esto puede llevar tiempu abondo, dependiendo del tamañu la base de datos)", "Checked database schema update for apps" : "Anovamientu del esquema de base de datos p'aplicaciones revisáu", "Updated \"%s\" to %s" : "Anováu \"%s\" a %s", + "Set log level to debug" : "Afita'l nivel de rexistru pa depurar", + "Reset log level" : "Reafitar nivel de rexistru", + "Starting code integrity check" : "Entamando la comprobación de la integridá del códigu", + "Finished code integrity check" : "Finada la comprobación de la integridá del códigu", + "%s (3rdparty)" : "%s (3rdparty)", + "%s (incompatible)" : "%s (incompatible)", + "Following apps have been disabled: %s" : "Siguientes aplicaciones deshabilitáronse: %s", + "Already up to date" : "Yá ta actualizáu", "Sunday" : "Domingu", "Monday" : "Llunes", "Tuesday" : "Martes", @@ -38,6 +65,13 @@ OC.L10N.register( "Thu." : "Xue.", "Fri." : "Vie.", "Sat." : "Sáb.", + "Su" : "Do", + "Mo" : "Llu", + "Tu" : "Ma", + "We" : "Mie", + "Th" : "Xue", + "Fr" : "Vie", + "Sa" : "Sa", "January" : "Xineru", "February" : "Febreru", "March" : "Marzu", @@ -62,7 +96,9 @@ OC.L10N.register( "Oct." : "Och.", "Nov." : "Pay.", "Dec." : "Avi.", + "There were problems with the code integrity check. More information…" : "Hebo un problema cola comprobación de la integridá del códigu. Más información...", "Settings" : "Axustes", + "Problem loading page, reloading in 5 seconds" : "Problema al cargar la páxina, volver cargar en 5 segundos", "Saving..." : "Guardando...", "Dismiss" : "Encaboxar", "seconds ago" : "hai segundos", @@ -76,6 +112,7 @@ OC.L10N.register( "Error loading file picker template: {error}" : "Fallu cargando'l ficheru de plantía d'escoyeta: {error}", "Ok" : "Aceutar", "Error loading message template: {error}" : "Fallu cargando'l mensaxe de la plantía: {error}", + "read-only" : "namái llectura", "_{count} file conflict_::_{count} file conflicts_" : ["{count} conflictu de ficheru","{count} conflictos de ficheru "], "One file conflict" : "Conflictu nun ficheru", "New Files" : "Ficheros nuevos", @@ -92,6 +129,8 @@ OC.L10N.register( "So-so password" : "Contraseña pasable", "Good password" : "Contraseña bona", "Strong password" : "Contraseña mui bona", + "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "El to sirvidor web entá nun ta configuráu afayadizamente pa permitir la sincronización de ficheros porque la interfaz WebDAV paez tar rota.", + "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our documentation." : "El to sirvidor web nun ta configuráu correchamente pa resolver \"{url}\". Pues atopar más información en nuesa documentación .", "Shared" : "Compartíu", "Shared with {recipients}" : "Compartío con {recipients}", "Error" : "Fallu", diff --git a/core/l10n/ast.json b/core/l10n/ast.json index 123201074a752..2f80bfb774172 100644 --- a/core/l10n/ast.json +++ b/core/l10n/ast.json @@ -1,11 +1,19 @@ { "translations": { + "Please select a file." : "Por favor esbilla un ficheru.", + "File is too big" : "Ficheru ye demasiáu grande", + "Invalid file provided" : "el ficheru apurríu nun ye válidu", "No image or file provided" : "Nun s'especificó nenguna imaxe o ficheru", "Unknown filetype" : "Triba de ficheru desconocida", "Invalid image" : "Imaxe inválida", + "An error occurred. Please contact your admin." : "Hebo un fallu. Por favor, contauta col to alministrador", "No temporary profile picture available, try again" : "Nengún perfil d'imaxe temporal disponible, intentalo de nueves", "No crop data provided" : "Nun s'apurrió'l retayu de datos", + "No valid crop data provided" : "El retayu de datos apurríu nun ye válidu", + "Crop is not square" : "El retayu nun ye cuadráu", "Couldn't reset password because the token is invalid" : "Nun pudo reaniciase la contraseña porque'l token ye inválidu", + "Couldn't reset password because the token is expired" : "Nun pudo reaniciase la contraseña porque'l token ye inválidu", "Couldn't send reset email. Please make sure your username is correct." : "Nun pudo unviase'l corréu. Por favor, asegurate que'l to nome d'usuariu seya correutu", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Nun pudo unviase'l corréu porque nun hai direición de corréu pa esti nome d'usuariu. Por favor, contauta col alministrador.", "%s password reset" : "%s restablecer contraseña", "Couldn't send reset email. Please contact your administrator." : "Nun pudo unviase'l corréu de reaniciu. Por favor, contauta col alministrador.", "Error loading tags" : "Fallu cargando les etiquetes", @@ -16,12 +24,31 @@ "Error favoriting" : "Fallu al marcar favoritos", "Error unfavoriting" : "Fallu al desmarcar favoritos", "Couldn't send mail to following users: %s " : "Nun pudo unviase'l corréu a los usuarios siguientes: %s", + "Preparing update" : "Preparando anovamientu", + "[%d / %d]: %s" : "[%d / %d]: %s", + "Repair warning: " : "Reparar avisu:", + "Repair error: " : "Reparar erru:", + "Please use the command line updater because automatic updating is disabled in the config.php." : "Por favor, usa l'actualización de llínea de comandos porque l'actualización automática ta deshabilitada nel config.php.", + "[%d / %d]: Checking table %s" : "[%d / %d]: Comprobando tabla %s", "Turned on maintenance mode" : "Activáu'l mou de caltenimientu", "Turned off maintenance mode" : "Apagáu'l mou de caltenimientu", + "Maintenance mode is kept active" : "La mou de caltenimientu caltiense activu", + "Updating database schema" : "Anovando esquema de base de datos", "Updated database" : "Base de datos anovada", + "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Comprobando si l'esquema de base de datos puede ser actualizáu (esto puede llevar tiempu abondo, dependiendo del tamañu la base de datos)", "Checked database schema update" : "Anovamientu del esquema de base de datos revisáu", + "Checking updates of apps" : "Comprobando anovamientos d'aplicaciones", + "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Comprobando si l'esquema de base de datos para %s puede ser actualizáu (esto puede llevar tiempu abondo, dependiendo del tamañu la base de datos)", "Checked database schema update for apps" : "Anovamientu del esquema de base de datos p'aplicaciones revisáu", "Updated \"%s\" to %s" : "Anováu \"%s\" a %s", + "Set log level to debug" : "Afita'l nivel de rexistru pa depurar", + "Reset log level" : "Reafitar nivel de rexistru", + "Starting code integrity check" : "Entamando la comprobación de la integridá del códigu", + "Finished code integrity check" : "Finada la comprobación de la integridá del códigu", + "%s (3rdparty)" : "%s (3rdparty)", + "%s (incompatible)" : "%s (incompatible)", + "Following apps have been disabled: %s" : "Siguientes aplicaciones deshabilitáronse: %s", + "Already up to date" : "Yá ta actualizáu", "Sunday" : "Domingu", "Monday" : "Llunes", "Tuesday" : "Martes", @@ -36,6 +63,13 @@ "Thu." : "Xue.", "Fri." : "Vie.", "Sat." : "Sáb.", + "Su" : "Do", + "Mo" : "Llu", + "Tu" : "Ma", + "We" : "Mie", + "Th" : "Xue", + "Fr" : "Vie", + "Sa" : "Sa", "January" : "Xineru", "February" : "Febreru", "March" : "Marzu", @@ -60,7 +94,9 @@ "Oct." : "Och.", "Nov." : "Pay.", "Dec." : "Avi.", + "There were problems with the code integrity check. More information…" : "Hebo un problema cola comprobación de la integridá del códigu. Más información...", "Settings" : "Axustes", + "Problem loading page, reloading in 5 seconds" : "Problema al cargar la páxina, volver cargar en 5 segundos", "Saving..." : "Guardando...", "Dismiss" : "Encaboxar", "seconds ago" : "hai segundos", @@ -74,6 +110,7 @@ "Error loading file picker template: {error}" : "Fallu cargando'l ficheru de plantía d'escoyeta: {error}", "Ok" : "Aceutar", "Error loading message template: {error}" : "Fallu cargando'l mensaxe de la plantía: {error}", + "read-only" : "namái llectura", "_{count} file conflict_::_{count} file conflicts_" : ["{count} conflictu de ficheru","{count} conflictos de ficheru "], "One file conflict" : "Conflictu nun ficheru", "New Files" : "Ficheros nuevos", @@ -90,6 +127,8 @@ "So-so password" : "Contraseña pasable", "Good password" : "Contraseña bona", "Strong password" : "Contraseña mui bona", + "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "El to sirvidor web entá nun ta configuráu afayadizamente pa permitir la sincronización de ficheros porque la interfaz WebDAV paez tar rota.", + "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our documentation." : "El to sirvidor web nun ta configuráu correchamente pa resolver \"{url}\". Pues atopar más información en nuesa documentación .", "Shared" : "Compartíu", "Shared with {recipients}" : "Compartío con {recipients}", "Error" : "Fallu", diff --git a/core/l10n/fr.js b/core/l10n/fr.js index b72796996f663..192da2e19a7d3 100644 --- a/core/l10n/fr.js +++ b/core/l10n/fr.js @@ -297,7 +297,9 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Veuillez contacter votre administrateur système si ce message persiste ou apparaît de façon inattendue.", "Thank you for your patience." : "Merci de votre patience.", "Two-step verification" : "Vérification en deux étapes", + "Enhanced security has been enabled for your account. Please authenticate using a second factor." : "La sécurité renforcée a été activée pour votre compte. Veuillez vous identifier en utilisant un deuxième facteur.", "Cancel login" : "Annuler la connexion", + "Please authenticate using the selected factor." : "Veuillez vous identifier en utilisant le facteur sélectionné.", "An error occured while verifying the token" : "Une erreur est survenue lors de la vérification du jeton", "You are accessing the server from an untrusted domain." : "Vous accédez au serveur à partir d'un domaine non approuvé.", "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Veuillez contacter votre administrateur. Si vous être l'administrateur de cette instance, configurez la variable \"trusted_domains\" dans le fichier config/config.php. Un exemple de configuration est fournit dans le fichier config/config.sample.php.", diff --git a/core/l10n/fr.json b/core/l10n/fr.json index 1edfbe71ab091..039f47ebaf213 100644 --- a/core/l10n/fr.json +++ b/core/l10n/fr.json @@ -295,7 +295,9 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Veuillez contacter votre administrateur système si ce message persiste ou apparaît de façon inattendue.", "Thank you for your patience." : "Merci de votre patience.", "Two-step verification" : "Vérification en deux étapes", + "Enhanced security has been enabled for your account. Please authenticate using a second factor." : "La sécurité renforcée a été activée pour votre compte. Veuillez vous identifier en utilisant un deuxième facteur.", "Cancel login" : "Annuler la connexion", + "Please authenticate using the selected factor." : "Veuillez vous identifier en utilisant le facteur sélectionné.", "An error occured while verifying the token" : "Une erreur est survenue lors de la vérification du jeton", "You are accessing the server from an untrusted domain." : "Vous accédez au serveur à partir d'un domaine non approuvé.", "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Veuillez contacter votre administrateur. Si vous être l'administrateur de cette instance, configurez la variable \"trusted_domains\" dans le fichier config/config.php. Un exemple de configuration est fournit dans le fichier config/config.sample.php.", diff --git a/core/l10n/lb.js b/core/l10n/lb.js index 966b5d289a4d9..c6865a9144111 100644 --- a/core/l10n/lb.js +++ b/core/l10n/lb.js @@ -1,15 +1,42 @@ OC.L10N.register( "core", { + "Please select a file." : "Wiel w.e.g. e Fichier aus.", + "File is too big" : "De Fichier ass ze grouss", + "Invalid file provided" : "Ongültege Fichier uginn", "No image or file provided" : "Kee Bild oder Fichier uginn", "Unknown filetype" : "Onbekannten Fichier Typ", - "Invalid image" : "Ongülteg d'Bild", + "Invalid image" : "Ongültegt Bild", + "An error occurred. Please contact your admin." : "Et ass e Feeler opgetrueden. W.e.g. kontaktéier däin Administrateur.", + "No temporary profile picture available, try again" : "Et ass keen temporäert Profilbild verfügbar, versich et nach emol.", + "Couldn't reset password because the token is invalid" : "D'Passwuert konnt net zeréck gesat ginn well den Token ongülteg ass", + "Couldn't reset password because the token is expired" : "D'Passwuert konnt net zeréck gesat ginn well den Token ofgelaf ass", + "Couldn't send reset email. Please make sure your username is correct." : "D'Email konnt net zeréck gesat ginn. Iwwerpréif w.e.g. op däi Passwuert richteg ass.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "D'Email fir zeréck ze setzen konnt net geschéckt ginn well et keng gülteg Emailadresse fir dëse Benotzernumm gëtt. W.e.g. kontaktéier däin Administrateur.", "%s password reset" : "%s Passwuert ass nei gesat", + "Couldn't send reset email. Please contact your administrator." : "D'Email fir zeréck ze setzen konnt net geschéckt ginn. W.e.g. kontaktéier däin Administrateur.", "Error tagging" : "Fehler beim Taggen", "Error untagging" : "Fehler beim Tag läschen", + "Error favoriting" : "Feeler beim favoriséieren", + "Error unfavoriting" : "Feeler beim defavoriséieren", + "Couldn't send mail to following users: %s " : "D'Email fir de folgende Benotzer konnt net geschéckt ginn: %s", + "Preparing update" : "D'Aktualiséierung gëtt virbereet", + "[%d / %d]: %s" : "[%d / %d]: %s", + "Repair warning: " : "Reparatur Warnung:", + "Repair error: " : "Reparéier de Feeler:", + "[%d / %d]: Checking table %s" : "[%d / %d]: Tabell gëtt gepréift %s", "Turned on maintenance mode" : "Maintenance Modus ass un", "Turned off maintenance mode" : "Maintenance Modus ass aus", + "Maintenance mode is kept active" : "De Maintenance Modus gëtt aktiv gehalen", + "Updating database schema" : "D'Schema vun der Datebank gëtt aktualiséiert", "Updated database" : "Datebank ass geupdate ginn", + "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Et gëtt gepréift ob d'Schema vun der Datebank aktualiséiert ka ginn (dëst kann ofhängeg vun der Gréisst vun der Datebank eng länger Zäit daueren)", + "Checked database schema update" : "D'Aktualiséierung vum Schema vun der Datebank gouf gepréift", + "Checking updates of apps" : "D'Aktualiséierung vun den Apps gëtt gepréift", + "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Et gëtt gepréift ob d'Schema vun der Datebank fir %s aktualiséiert ka ginn (dëst kann ofhängeg vun der Datebank eng länger Zäit daueren)", + "Checked database schema update for apps" : "D'Aktualiséierung vum Schema vun der Datebank fir Applikatioune gouf gepréift", + "Updated \"%s\" to %s" : "\"%s\" gouf op %s aktualiséiert", + "Already up to date" : "Schonn um neiste Stand", "Sunday" : "Sonndeg", "Monday" : "Méindeg", "Tuesday" : "Dënschdeg", @@ -24,6 +51,13 @@ OC.L10N.register( "Thu." : "Do.", "Fri." : "Fr.", "Sat." : "Sa.", + "Su" : "SO", + "Mo" : "ME", + "Tu" : "DE", + "We" : "ME", + "Th" : "DO", + "Fr" : "FR", + "Sa" : "SA", "January" : "Januar", "February" : "Februar", "March" : "Mäerz", @@ -49,23 +83,39 @@ OC.L10N.register( "Nov." : "Nov.", "Dec." : "Dez.", "Settings" : "Astellungen", + "Problem loading page, reloading in 5 seconds" : "Et gouf e Problem beim Luede vun der Säit, a 5 Sekonnen gëtt nei gelueden", "Saving..." : "Speicheren...", + "Dismiss" : "Verworf", "seconds ago" : "Sekonnen hier", + "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator." : "De Link fir d'Passwuert zeréckzesetzen gouf un deng E-Mail-Adress geschéckt. Falls d'Mail net enger raisonnabeler Zäitspan ukënnt, kuck w.e.g. an dengem Spam-Dossier. Wann do och keng Mail ass, fro w.e.g. däin Administrateur.", + "Your files are encrypted. If you haven't enabled the recovery key, there will be no way to get your data back after your password is reset.
If you are not sure what to do, please contact your administrator before you continue.
Do you really want to continue?" : "Deng Fichiere si verschlësselt. Falls du de Recuperatiouns-Schlëssel net aktivéiert hues, gëtt et keng Méiglechkeet nees un deng Daten ze komme wann däi Passwuert bis zeréckgesat gouf. Falls du net sécher bass wat s de maache soll, kontaktéier w.e.g. däin Administrateur éiers de weiderfiers. Bass de sécher dass de weidermaache wëlls?", + "I know what I'm doing" : "Ech weess wat ech maachen", + "Password can not be changed. Please contact your administrator." : "D'Passwuert kann net geännert ginn. W.e.g. kontaktéier däin Administrateur.", "No" : "Nee", "Yes" : "Jo", "Choose" : "Auswielen", "Ok" : "OK", + "Error loading message template: {error}" : "Feeler beim Luede vun der Noorichte Virlag: {Feeler}", + "read-only" : "Nëmme liesen", + "New Files" : "Nei Fichieren", + "Already existing files" : "D'Fichieren existéiere schonn", "Which files do you want to keep?" : "Weieng Fichieren wëlls de gär behalen?", + "If you select both versions, the copied file will have a number added to its name." : "Wann s de déi zwou Versiounen auswiels kritt de kopéierte Fichier eng Nummer bei den Numm derbäi gesat", "Cancel" : "Ofbriechen", "Continue" : "Weider", "(all selected)" : "(all ausgewielt)", "({count} selected)" : "({count} ausgewielt)", + "Error loading file exists template" : "Feeler beim Luede vum Fichier existéiert eng Virlag", "Very weak password" : "Ganz schwaacht Passwuert", "Weak password" : "Schwaacht Passwuert", "So-so password" : "La-La Passwuert", "Good password" : "Gutt Passwuert", "Strong password" : "Staarkt Passwuert", + "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Däi Web Server ass net richteg agestallt fir d'Fichier Selektioun ze erlaben well den WebDAV Interface schéngt futti ze sinn.", + "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our documentation." : "Däi Web Server ass net richteg agestallt fir \"{url}\" ze léisen. Méi Informatiounen fënns de op eisem Dokumentatioun.", + "This server has no working Internet connection. 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. We suggest to enable Internet connection for this server if you want to have all features." : "D'Internet Verbindung fir dëse Server funktionéiert net. Dat bedeit dass e puer vun dëse Funktiounen wéi eng extern Späicherplaz ariichten, Notifikatiounen iwwer Aktualiséierungen oder d'Installéieren vu friemen Apps net funktionéiere wäert. Fichieren op Distanz erreechen an d'Schécke vu Notifikatioun Emailen kéinnten och net funktionéieren. Mir roden fir d'Internet Verbindung fir dëse Server hierzestellen wann s de all d'Funktioune wëlls hunn.", "Shared" : "Gedeelt", + "Shared with {recipients}" : "Gedeelt mat {Empfänger}", "Error" : "Feeler", "Error while sharing" : "Feeler beim Deelen", "Error while unsharing" : "Feeler beim Annuléiere vum Deelen", @@ -85,6 +135,7 @@ OC.L10N.register( "Send" : "Schécken", "Sending ..." : "Gëtt geschéckt...", "Email sent" : "Email geschéckt", + "Send link via email" : "De Link iwwer E-Mail schécken", "Shared with you and the group {group} by {owner}" : "Gedeelt mat dir an der Grupp {group} vum {owner}", "Shared with you by {owner}" : "Gedeelt mat dir vum {owner}", "group" : "Grupp", @@ -97,43 +148,122 @@ OC.L10N.register( "change" : "änneren", "delete" : "läschen", "access control" : "Zougrëffskontroll", + "Could not unshare" : "Konnt net ongedeelt ginn", + "Share details could not be loaded for this item." : "D'Detailer vum Deelen konnten net geluede ginn fir dësen Artikel.", + "No users or groups found for {search}" : "Keng Benotzer oder Gruppe fonnt fir {Sich}", + "No users found for {search}" : "Keng Benotzer fonnt fir {Sich}", + "An error occurred. Please try again" : "Et ass e Fehler opgetrueden. W.e.g. probéier nach emol", "Share" : "Deelen", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Mat Leit vun aneren ownCloud deelen, déi d'Syntax username@example.com/owncloud benotzen", + "Share with users…" : "Mat Benotzer deelen ...", + "Share with users, groups or remote users…" : "Mat Benotzer, Gruppen oder Benotzer op Distanz deelen ...", + "Share with users or groups…" : "Mat Benotzer oder Gruppen deelen...", + "Share with users or remote users…" : "Mat Benotzer oder mat Benotzer op Distanz deelen ...", + "Error removing share" : "Fehler beim Läschen vum Bäitrag", "Warning" : "Warnung", + "Error while sending notification" : "Feeler beim Schécke vun der Notifikatioun", + "restricted" : "Ageschränkt", + "invisible" : "Onsiichtbar", "Delete" : "Läschen", "Rename" : "Ëmbenennen", "The object type is not specified." : "Den Typ vum Object ass net uginn.", "Enter new" : "Gëff nei an", "Add" : "Dobäisetzen", "Edit tags" : "Tags editéieren", - "The update was unsuccessful. Please report this issue to the ownCloud community." : "Den Update war net erfollegräich. Mell dëse Problem w.e.gl derownCloud-Community.", - "The update was successful. Redirecting you to ownCloud now." : "Den Update war erfollegräich. Du gëss elo bei d'ownCloud ëmgeleet.", + "unknown text" : "Onbekannten Text", + "Hello world!" : "Hallo Welt!", + "sunny" : "Sonneg", + "Hello {name}, the weather is {weather}" : "Hallo {Numm}, d'Wieder ass {Wieder}", + "Hello {name}" : "Hallo {Numm}", + "new" : "Nei", + "_download %n file_::_download %n files_" : ["%n Fichier eroflueden","%n Fichieren eroflueden"], + "Updating to {version}" : "Aktualiséieren op {Versioun}", + "An error occurred." : "Et ass e Feeler opgetrueden", + "Please reload the page." : "Lued w.e.g. d'Säit nei.", + "The update was unsuccessful. For more information check our forum post covering this issue." : "D'Aktualiséierung war net erfollegräich. Fir méi Informatiounen Kuck eise Forum Bäitrag deen dëst Thema behandelt.", + "The update was unsuccessful. Please report this issue to the ownCloud community." : "D'Aktualiséierung war net erfollegräich. Mell dëse Problem w.e.gl derownCloud-Community.", + "The update was successful. There were warnings." : "D'Aktualiséierung war erfollegräich. Et goufe Warnungen.", + "The update was successful. Redirecting you to ownCloud now." : "D'Aktualiséierung war erfollegräich. Du gëss elo bei d'ownCloud ëmgeleet.", + "Searching other places" : "Op anere Plaaze sichen", + "No search results in other folders" : "Keng Sich Resultater an aneren Dossieren", "Personal" : "Perséinlech", "Users" : "Benotzer", "Apps" : "Applikatiounen", "Admin" : "Admin", "Help" : "Hëllef", "Access forbidden" : "Zougrëff net erlaabt", + "File not found" : "Fichier net fonnt", + "The specified document has not been found on the server." : "Dat ausgewielt Dokument konnt net op dësem Server fonnt ginn.", + "You can click here to return to %s." : "Du kanns hei klicken fir bei %s zeréck ze goen.", + "Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" : "Hallo,\n\nech wëll just Bescheed soen dass den/d' %s, »%s« mat dir gedeelt huet.\nUkucken: %s\n", "Cheers!" : "Prost!", + "Internal Server Error" : "Interne Server Feeler", + "The server encountered an internal error and was unable to complete your request." : "De Server huet en interne Feeler festgestallt an konnt deng Ufro net ëmsetzen", + "Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report." : "W.e.g. kontaktéier de Server Administrateur wann dëse Feeler e puer Mol optrëtt an sëtz d'technesch Detailer an de Rapport derbäi.", + "More details can be found in the server log." : "Méi Detailer kënnen am Server Log fonnt ginn.", + "Technical details" : "Technesch Detailer", + "Remote Address: %s" : "D'Adress op Distanz: %s", + "Request ID: %s" : "ID ufroen: %s", + "Type: %s" : "Typ: %s", + "Code: %s" : "Code: %s", + "Message: %s" : "Noriicht: %s", + "File: %s" : "Fichier: %s", + "Line: %s" : "Zeil: %s", + "Trace" : "Spuren", + "Security warning" : "Sécherheets Warnung", "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." : "Däin Daten-Dossier an deng Fichieren si wahrscheinlech iwwert den Internet accessibel well den .htaccess-Fichier net funktionnéiert.", "Create an admin account" : "En Admin-Account uleeën", "Username" : "Benotzernumm", + "Storage & database" : "Speicherplaz & Datebank", "Data folder" : "Daten-Dossier", "Configure the database" : "D'Datebank konfiguréieren", + "Only %s is available." : "Nëmmen den %s ass verfügbar.", + "Install and activate additional PHP modules to choose other database types." : "Installéier an aktivéier zousätzlech PHP Moduler fir aner Forme vun Datebanken auszewielen.", + "For more details check out the documentation." : "Kuck an der Dokumentatioun fir méi Informatiounen.", "Database user" : "Datebank-Benotzer", "Database password" : "Datebank-Passwuert", "Database name" : "Datebank Numm", "Database tablespace" : "Tabelle-Plaz vun der Datebank", "Database host" : "Datebank-Server", + "Performance warning" : "Leeschtungs Warnung", + "SQLite will be used as database." : "SQLite wäert als Datebank benotzt ginn.", + "For larger installations we recommend to choose a different database backend." : "Fir méi grouss Installatiounen recommandéiere mir fir en aneren Datebanken Backend ze benotzen.", "Finish setup" : "Installatioun ofschléissen", "Finishing …" : "Schléissen of ...", + "Need help?" : "Brauchs de Hëllef?", + "See the documentation" : "Kuck an der Dokumentatioun", + "Hey there,

just letting you know that %s shared %s with you.
View it!

" : "Hallo,

ech wëll just Bescheed soen dass den/d' %s %s mat dir gedeelt huet.
Ukucken!

", + "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Dës Applikatioun verlaangt JavaScript fir kënne korrekt auszeféieren. W.e.g {linkstart} schalt JavaScript an {linkend} a luet d'Säit nei.", "Log out" : "Ofmellen", "Search" : "Sichen", + "Server side authentication failed!" : "D'Autentifikatioun vun der Säit vum Server huet net geklappt!", + "Please contact your administrator." : "W.e.g. kontaktéier däin Administrateur.", + "An internal error occurred." : "Et ass en interne Feeler opgetrueden.", + "Please try again or contact your administrator." : "W.e.g. versich et nach emol oder kontaktéier däin Administrateur.", + "Username or email" : "Benotzernumm oder Email", "Log in" : "Umellen", + "Wrong password. Reset it?" : "Falscht Passwuert. Wëlls de et zeréck setzen?", + "Wrong password." : "Falscht Passwuert.", + "Stay logged in" : "Bleif ageloggt.", "Alternative Logins" : "Alternativ Umeldungen", "Use the following link to reset your password: {link}" : "Benotz folgende Link fir däi Passwuert zréckzesetzen: {link}", "New password" : "Neit Passwuert", + "New Password" : "Neit Passwuert", "Reset password" : "Passwuert zréck setzen", - "Thank you for your patience." : "Merci fir deng Gedold." + "This ownCloud instance is currently in single user mode." : "Dës ownCloud Instanz ass am Moment am eenzel Benotzer Modus.", + "This means only administrators can use the instance." : "Dëst bedeit dass just d'Administrateuren d'Instanz benotze kënnen.", + "Thank you for your patience." : "Merci fir deng Gedold.", + "Two-step verification" : "Verifikatioun mat zwee Schrëtt", + "Cancel login" : "Login ofbriechen", + "Please authenticate using the selected factor." : "W.e.g. authentifizéier dech andeems de den ausgewielten Facteur benotz.", + "An error occured while verifying the token" : "Beim Token iwwerpréiwen ass e Feeler opgetrueden", + "You are accessing the server from an untrusted domain." : "Du gräifs vun enger net vertrauensvoller Domän op dëse Server zou.", + "Add \"%s\" as trusted domain" : "\"%s\" als zouverlässeg Domän derbäi setzen", + "App update required" : "App Aktualiséierung néideg", + "%s will be updated to version %s" : "%s wäert aktualiséiert ginn op d'Versioun %s", + "These apps will be updated:" : "D!es Apps wäerten aktualiséiert ginn:", + "These incompatible apps will be disabled:" : "Dës inkompatibel Apps wäerten ofgeschalt ginn:", + "The theme %s has been disabled." : "D'Thema %s gouf ofgeschalt.", + "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "W.e.g. géi sécher dass d'Datebank, de configuréierten Dossier an den Daten Dossier ofgeséchert sinn éiers de weider gees." }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/lb.json b/core/l10n/lb.json index 607c3e6abb777..f3af3f00ee6d2 100644 --- a/core/l10n/lb.json +++ b/core/l10n/lb.json @@ -1,13 +1,40 @@ { "translations": { + "Please select a file." : "Wiel w.e.g. e Fichier aus.", + "File is too big" : "De Fichier ass ze grouss", + "Invalid file provided" : "Ongültege Fichier uginn", "No image or file provided" : "Kee Bild oder Fichier uginn", "Unknown filetype" : "Onbekannten Fichier Typ", - "Invalid image" : "Ongülteg d'Bild", + "Invalid image" : "Ongültegt Bild", + "An error occurred. Please contact your admin." : "Et ass e Feeler opgetrueden. W.e.g. kontaktéier däin Administrateur.", + "No temporary profile picture available, try again" : "Et ass keen temporäert Profilbild verfügbar, versich et nach emol.", + "Couldn't reset password because the token is invalid" : "D'Passwuert konnt net zeréck gesat ginn well den Token ongülteg ass", + "Couldn't reset password because the token is expired" : "D'Passwuert konnt net zeréck gesat ginn well den Token ofgelaf ass", + "Couldn't send reset email. Please make sure your username is correct." : "D'Email konnt net zeréck gesat ginn. Iwwerpréif w.e.g. op däi Passwuert richteg ass.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "D'Email fir zeréck ze setzen konnt net geschéckt ginn well et keng gülteg Emailadresse fir dëse Benotzernumm gëtt. W.e.g. kontaktéier däin Administrateur.", "%s password reset" : "%s Passwuert ass nei gesat", + "Couldn't send reset email. Please contact your administrator." : "D'Email fir zeréck ze setzen konnt net geschéckt ginn. W.e.g. kontaktéier däin Administrateur.", "Error tagging" : "Fehler beim Taggen", "Error untagging" : "Fehler beim Tag läschen", + "Error favoriting" : "Feeler beim favoriséieren", + "Error unfavoriting" : "Feeler beim defavoriséieren", + "Couldn't send mail to following users: %s " : "D'Email fir de folgende Benotzer konnt net geschéckt ginn: %s", + "Preparing update" : "D'Aktualiséierung gëtt virbereet", + "[%d / %d]: %s" : "[%d / %d]: %s", + "Repair warning: " : "Reparatur Warnung:", + "Repair error: " : "Reparéier de Feeler:", + "[%d / %d]: Checking table %s" : "[%d / %d]: Tabell gëtt gepréift %s", "Turned on maintenance mode" : "Maintenance Modus ass un", "Turned off maintenance mode" : "Maintenance Modus ass aus", + "Maintenance mode is kept active" : "De Maintenance Modus gëtt aktiv gehalen", + "Updating database schema" : "D'Schema vun der Datebank gëtt aktualiséiert", "Updated database" : "Datebank ass geupdate ginn", + "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Et gëtt gepréift ob d'Schema vun der Datebank aktualiséiert ka ginn (dëst kann ofhängeg vun der Gréisst vun der Datebank eng länger Zäit daueren)", + "Checked database schema update" : "D'Aktualiséierung vum Schema vun der Datebank gouf gepréift", + "Checking updates of apps" : "D'Aktualiséierung vun den Apps gëtt gepréift", + "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Et gëtt gepréift ob d'Schema vun der Datebank fir %s aktualiséiert ka ginn (dëst kann ofhängeg vun der Datebank eng länger Zäit daueren)", + "Checked database schema update for apps" : "D'Aktualiséierung vum Schema vun der Datebank fir Applikatioune gouf gepréift", + "Updated \"%s\" to %s" : "\"%s\" gouf op %s aktualiséiert", + "Already up to date" : "Schonn um neiste Stand", "Sunday" : "Sonndeg", "Monday" : "Méindeg", "Tuesday" : "Dënschdeg", @@ -22,6 +49,13 @@ "Thu." : "Do.", "Fri." : "Fr.", "Sat." : "Sa.", + "Su" : "SO", + "Mo" : "ME", + "Tu" : "DE", + "We" : "ME", + "Th" : "DO", + "Fr" : "FR", + "Sa" : "SA", "January" : "Januar", "February" : "Februar", "March" : "Mäerz", @@ -47,23 +81,39 @@ "Nov." : "Nov.", "Dec." : "Dez.", "Settings" : "Astellungen", + "Problem loading page, reloading in 5 seconds" : "Et gouf e Problem beim Luede vun der Säit, a 5 Sekonnen gëtt nei gelueden", "Saving..." : "Speicheren...", + "Dismiss" : "Verworf", "seconds ago" : "Sekonnen hier", + "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator." : "De Link fir d'Passwuert zeréckzesetzen gouf un deng E-Mail-Adress geschéckt. Falls d'Mail net enger raisonnabeler Zäitspan ukënnt, kuck w.e.g. an dengem Spam-Dossier. Wann do och keng Mail ass, fro w.e.g. däin Administrateur.", + "Your files are encrypted. If you haven't enabled the recovery key, there will be no way to get your data back after your password is reset.
If you are not sure what to do, please contact your administrator before you continue.
Do you really want to continue?" : "Deng Fichiere si verschlësselt. Falls du de Recuperatiouns-Schlëssel net aktivéiert hues, gëtt et keng Méiglechkeet nees un deng Daten ze komme wann däi Passwuert bis zeréckgesat gouf. Falls du net sécher bass wat s de maache soll, kontaktéier w.e.g. däin Administrateur éiers de weiderfiers. Bass de sécher dass de weidermaache wëlls?", + "I know what I'm doing" : "Ech weess wat ech maachen", + "Password can not be changed. Please contact your administrator." : "D'Passwuert kann net geännert ginn. W.e.g. kontaktéier däin Administrateur.", "No" : "Nee", "Yes" : "Jo", "Choose" : "Auswielen", "Ok" : "OK", + "Error loading message template: {error}" : "Feeler beim Luede vun der Noorichte Virlag: {Feeler}", + "read-only" : "Nëmme liesen", + "New Files" : "Nei Fichieren", + "Already existing files" : "D'Fichieren existéiere schonn", "Which files do you want to keep?" : "Weieng Fichieren wëlls de gär behalen?", + "If you select both versions, the copied file will have a number added to its name." : "Wann s de déi zwou Versiounen auswiels kritt de kopéierte Fichier eng Nummer bei den Numm derbäi gesat", "Cancel" : "Ofbriechen", "Continue" : "Weider", "(all selected)" : "(all ausgewielt)", "({count} selected)" : "({count} ausgewielt)", + "Error loading file exists template" : "Feeler beim Luede vum Fichier existéiert eng Virlag", "Very weak password" : "Ganz schwaacht Passwuert", "Weak password" : "Schwaacht Passwuert", "So-so password" : "La-La Passwuert", "Good password" : "Gutt Passwuert", "Strong password" : "Staarkt Passwuert", + "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Däi Web Server ass net richteg agestallt fir d'Fichier Selektioun ze erlaben well den WebDAV Interface schéngt futti ze sinn.", + "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our documentation." : "Däi Web Server ass net richteg agestallt fir \"{url}\" ze léisen. Méi Informatiounen fënns de op eisem Dokumentatioun.", + "This server has no working Internet connection. 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. We suggest to enable Internet connection for this server if you want to have all features." : "D'Internet Verbindung fir dëse Server funktionéiert net. Dat bedeit dass e puer vun dëse Funktiounen wéi eng extern Späicherplaz ariichten, Notifikatiounen iwwer Aktualiséierungen oder d'Installéieren vu friemen Apps net funktionéiere wäert. Fichieren op Distanz erreechen an d'Schécke vu Notifikatioun Emailen kéinnten och net funktionéieren. Mir roden fir d'Internet Verbindung fir dëse Server hierzestellen wann s de all d'Funktioune wëlls hunn.", "Shared" : "Gedeelt", + "Shared with {recipients}" : "Gedeelt mat {Empfänger}", "Error" : "Feeler", "Error while sharing" : "Feeler beim Deelen", "Error while unsharing" : "Feeler beim Annuléiere vum Deelen", @@ -83,6 +133,7 @@ "Send" : "Schécken", "Sending ..." : "Gëtt geschéckt...", "Email sent" : "Email geschéckt", + "Send link via email" : "De Link iwwer E-Mail schécken", "Shared with you and the group {group} by {owner}" : "Gedeelt mat dir an der Grupp {group} vum {owner}", "Shared with you by {owner}" : "Gedeelt mat dir vum {owner}", "group" : "Grupp", @@ -95,43 +146,122 @@ "change" : "änneren", "delete" : "läschen", "access control" : "Zougrëffskontroll", + "Could not unshare" : "Konnt net ongedeelt ginn", + "Share details could not be loaded for this item." : "D'Detailer vum Deelen konnten net geluede ginn fir dësen Artikel.", + "No users or groups found for {search}" : "Keng Benotzer oder Gruppe fonnt fir {Sich}", + "No users found for {search}" : "Keng Benotzer fonnt fir {Sich}", + "An error occurred. Please try again" : "Et ass e Fehler opgetrueden. W.e.g. probéier nach emol", "Share" : "Deelen", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Mat Leit vun aneren ownCloud deelen, déi d'Syntax username@example.com/owncloud benotzen", + "Share with users…" : "Mat Benotzer deelen ...", + "Share with users, groups or remote users…" : "Mat Benotzer, Gruppen oder Benotzer op Distanz deelen ...", + "Share with users or groups…" : "Mat Benotzer oder Gruppen deelen...", + "Share with users or remote users…" : "Mat Benotzer oder mat Benotzer op Distanz deelen ...", + "Error removing share" : "Fehler beim Läschen vum Bäitrag", "Warning" : "Warnung", + "Error while sending notification" : "Feeler beim Schécke vun der Notifikatioun", + "restricted" : "Ageschränkt", + "invisible" : "Onsiichtbar", "Delete" : "Läschen", "Rename" : "Ëmbenennen", "The object type is not specified." : "Den Typ vum Object ass net uginn.", "Enter new" : "Gëff nei an", "Add" : "Dobäisetzen", "Edit tags" : "Tags editéieren", - "The update was unsuccessful. Please report this issue to the ownCloud community." : "Den Update war net erfollegräich. Mell dëse Problem w.e.gl derownCloud-Community.", - "The update was successful. Redirecting you to ownCloud now." : "Den Update war erfollegräich. Du gëss elo bei d'ownCloud ëmgeleet.", + "unknown text" : "Onbekannten Text", + "Hello world!" : "Hallo Welt!", + "sunny" : "Sonneg", + "Hello {name}, the weather is {weather}" : "Hallo {Numm}, d'Wieder ass {Wieder}", + "Hello {name}" : "Hallo {Numm}", + "new" : "Nei", + "_download %n file_::_download %n files_" : ["%n Fichier eroflueden","%n Fichieren eroflueden"], + "Updating to {version}" : "Aktualiséieren op {Versioun}", + "An error occurred." : "Et ass e Feeler opgetrueden", + "Please reload the page." : "Lued w.e.g. d'Säit nei.", + "The update was unsuccessful. For more information check our forum post covering this issue." : "D'Aktualiséierung war net erfollegräich. Fir méi Informatiounen Kuck eise Forum Bäitrag deen dëst Thema behandelt.", + "The update was unsuccessful. Please report this issue to the ownCloud community." : "D'Aktualiséierung war net erfollegräich. Mell dëse Problem w.e.gl derownCloud-Community.", + "The update was successful. There were warnings." : "D'Aktualiséierung war erfollegräich. Et goufe Warnungen.", + "The update was successful. Redirecting you to ownCloud now." : "D'Aktualiséierung war erfollegräich. Du gëss elo bei d'ownCloud ëmgeleet.", + "Searching other places" : "Op anere Plaaze sichen", + "No search results in other folders" : "Keng Sich Resultater an aneren Dossieren", "Personal" : "Perséinlech", "Users" : "Benotzer", "Apps" : "Applikatiounen", "Admin" : "Admin", "Help" : "Hëllef", "Access forbidden" : "Zougrëff net erlaabt", + "File not found" : "Fichier net fonnt", + "The specified document has not been found on the server." : "Dat ausgewielt Dokument konnt net op dësem Server fonnt ginn.", + "You can click here to return to %s." : "Du kanns hei klicken fir bei %s zeréck ze goen.", + "Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" : "Hallo,\n\nech wëll just Bescheed soen dass den/d' %s, »%s« mat dir gedeelt huet.\nUkucken: %s\n", "Cheers!" : "Prost!", + "Internal Server Error" : "Interne Server Feeler", + "The server encountered an internal error and was unable to complete your request." : "De Server huet en interne Feeler festgestallt an konnt deng Ufro net ëmsetzen", + "Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report." : "W.e.g. kontaktéier de Server Administrateur wann dëse Feeler e puer Mol optrëtt an sëtz d'technesch Detailer an de Rapport derbäi.", + "More details can be found in the server log." : "Méi Detailer kënnen am Server Log fonnt ginn.", + "Technical details" : "Technesch Detailer", + "Remote Address: %s" : "D'Adress op Distanz: %s", + "Request ID: %s" : "ID ufroen: %s", + "Type: %s" : "Typ: %s", + "Code: %s" : "Code: %s", + "Message: %s" : "Noriicht: %s", + "File: %s" : "Fichier: %s", + "Line: %s" : "Zeil: %s", + "Trace" : "Spuren", + "Security warning" : "Sécherheets Warnung", "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." : "Däin Daten-Dossier an deng Fichieren si wahrscheinlech iwwert den Internet accessibel well den .htaccess-Fichier net funktionnéiert.", "Create an admin account" : "En Admin-Account uleeën", "Username" : "Benotzernumm", + "Storage & database" : "Speicherplaz & Datebank", "Data folder" : "Daten-Dossier", "Configure the database" : "D'Datebank konfiguréieren", + "Only %s is available." : "Nëmmen den %s ass verfügbar.", + "Install and activate additional PHP modules to choose other database types." : "Installéier an aktivéier zousätzlech PHP Moduler fir aner Forme vun Datebanken auszewielen.", + "For more details check out the documentation." : "Kuck an der Dokumentatioun fir méi Informatiounen.", "Database user" : "Datebank-Benotzer", "Database password" : "Datebank-Passwuert", "Database name" : "Datebank Numm", "Database tablespace" : "Tabelle-Plaz vun der Datebank", "Database host" : "Datebank-Server", + "Performance warning" : "Leeschtungs Warnung", + "SQLite will be used as database." : "SQLite wäert als Datebank benotzt ginn.", + "For larger installations we recommend to choose a different database backend." : "Fir méi grouss Installatiounen recommandéiere mir fir en aneren Datebanken Backend ze benotzen.", "Finish setup" : "Installatioun ofschléissen", "Finishing …" : "Schléissen of ...", + "Need help?" : "Brauchs de Hëllef?", + "See the documentation" : "Kuck an der Dokumentatioun", + "Hey there,

just letting you know that %s shared %s with you.
View it!

" : "Hallo,

ech wëll just Bescheed soen dass den/d' %s %s mat dir gedeelt huet.
Ukucken!

", + "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Dës Applikatioun verlaangt JavaScript fir kënne korrekt auszeféieren. W.e.g {linkstart} schalt JavaScript an {linkend} a luet d'Säit nei.", "Log out" : "Ofmellen", "Search" : "Sichen", + "Server side authentication failed!" : "D'Autentifikatioun vun der Säit vum Server huet net geklappt!", + "Please contact your administrator." : "W.e.g. kontaktéier däin Administrateur.", + "An internal error occurred." : "Et ass en interne Feeler opgetrueden.", + "Please try again or contact your administrator." : "W.e.g. versich et nach emol oder kontaktéier däin Administrateur.", + "Username or email" : "Benotzernumm oder Email", "Log in" : "Umellen", + "Wrong password. Reset it?" : "Falscht Passwuert. Wëlls de et zeréck setzen?", + "Wrong password." : "Falscht Passwuert.", + "Stay logged in" : "Bleif ageloggt.", "Alternative Logins" : "Alternativ Umeldungen", "Use the following link to reset your password: {link}" : "Benotz folgende Link fir däi Passwuert zréckzesetzen: {link}", "New password" : "Neit Passwuert", + "New Password" : "Neit Passwuert", "Reset password" : "Passwuert zréck setzen", - "Thank you for your patience." : "Merci fir deng Gedold." + "This ownCloud instance is currently in single user mode." : "Dës ownCloud Instanz ass am Moment am eenzel Benotzer Modus.", + "This means only administrators can use the instance." : "Dëst bedeit dass just d'Administrateuren d'Instanz benotze kënnen.", + "Thank you for your patience." : "Merci fir deng Gedold.", + "Two-step verification" : "Verifikatioun mat zwee Schrëtt", + "Cancel login" : "Login ofbriechen", + "Please authenticate using the selected factor." : "W.e.g. authentifizéier dech andeems de den ausgewielten Facteur benotz.", + "An error occured while verifying the token" : "Beim Token iwwerpréiwen ass e Feeler opgetrueden", + "You are accessing the server from an untrusted domain." : "Du gräifs vun enger net vertrauensvoller Domän op dëse Server zou.", + "Add \"%s\" as trusted domain" : "\"%s\" als zouverlässeg Domän derbäi setzen", + "App update required" : "App Aktualiséierung néideg", + "%s will be updated to version %s" : "%s wäert aktualiséiert ginn op d'Versioun %s", + "These apps will be updated:" : "D!es Apps wäerten aktualiséiert ginn:", + "These incompatible apps will be disabled:" : "Dës inkompatibel Apps wäerten ofgeschalt ginn:", + "The theme %s has been disabled." : "D'Thema %s gouf ofgeschalt.", + "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "W.e.g. géi sécher dass d'Datebank, de configuréierten Dossier an den Daten Dossier ofgeséchert sinn éiers de weider gees." },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/core/l10n/sl.js b/core/l10n/sl.js index 7481a2df970b5..156cb8901e45e 100644 --- a/core/l10n/sl.js +++ b/core/l10n/sl.js @@ -197,6 +197,7 @@ OC.L10N.register( "({scope})" : "({scope})", "Delete" : "Izbriši", "Rename" : "Preimenuj", + "Collaborative tags" : "Oznake za sodelovanje", "The object type is not specified." : "Vrsta predmeta ni podana.", "Enter new" : "Vnesite novo", "Add" : "Dodaj", @@ -293,6 +294,8 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Stopite v stik s skrbnikom sistema, če se bo sporočilo še naprej nepričakovano prikazovalo.", "Thank you for your patience." : "Hvala za potrpežljivost!", "Two-step verification" : "Dvostopenjsko overjanje", + "Cancel login" : "Prekliči prijavo", + "An error occured while verifying the token" : "Napaka se je zgodila med preverjanjem ključa", "You are accessing the server from an untrusted domain." : "Trenutno je vzpostavljena povezava s strežnikom preko ne-varne domene.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Glede na nastavitve bi lahko kot skrbnik uporabili spodnji gumb in domeno ročno določili kot varno.", "Add \"%s\" as trusted domain" : "Dodaj \"%s\" kot varno domeno", diff --git a/core/l10n/sl.json b/core/l10n/sl.json index bf1a36f731ef3..1f374bef52aaa 100644 --- a/core/l10n/sl.json +++ b/core/l10n/sl.json @@ -195,6 +195,7 @@ "({scope})" : "({scope})", "Delete" : "Izbriši", "Rename" : "Preimenuj", + "Collaborative tags" : "Oznake za sodelovanje", "The object type is not specified." : "Vrsta predmeta ni podana.", "Enter new" : "Vnesite novo", "Add" : "Dodaj", @@ -291,6 +292,8 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Stopite v stik s skrbnikom sistema, če se bo sporočilo še naprej nepričakovano prikazovalo.", "Thank you for your patience." : "Hvala za potrpežljivost!", "Two-step verification" : "Dvostopenjsko overjanje", + "Cancel login" : "Prekliči prijavo", + "An error occured while verifying the token" : "Napaka se je zgodila med preverjanjem ključa", "You are accessing the server from an untrusted domain." : "Trenutno je vzpostavljena povezava s strežnikom preko ne-varne domene.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Glede na nastavitve bi lahko kot skrbnik uporabili spodnji gumb in domeno ročno določili kot varno.", "Add \"%s\" as trusted domain" : "Dodaj \"%s\" kot varno domeno", diff --git a/lib/l10n/hu_HU.js b/lib/l10n/hu_HU.js index 4c17b946ca4eb..77cf7a401b042 100644 --- a/lib/l10n/hu_HU.js +++ b/lib/l10n/hu_HU.js @@ -9,8 +9,12 @@ OC.L10N.register( "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Úgy tűnik a példakonfigurációt próbálja ténylegesen használni. Ez nem támogatott, és működésképtelenné teheti a telepítést. Kérjük olvassa el a dokumentációt és azt követően változtasson a config.php-n!", "PHP %s or higher is required." : "PHP %s vagy ennél újabb szükséges.", "PHP with a version lower than %s is required." : "Ennél régebbi PHP szükséges: %s.", + "%sbit or higher PHP required." : "%sbit vagy ennél magasabb szükséges.", "Following databases are supported: %s" : "A következő adatbázisok támogatottak: %s", + "The command line tool %s could not be found" : "A parancssori eszköz %s nem található", "The library %s is not available." : "A könyvtár %s nem áll rendelkezésre.", + "Library %s with a version higher than %s is required - available version %s." : "A könyvtár a %s verzióval nagyobb mint a szükséges %s - elérhető verzió %s", + "Library %s with a version lower than %s is required - available version %s." : "A könyvtár a %s verzióval alacsonyabb mint a szükséges %s - elérhető verzió %s", "Following platforms are supported: %s" : "Ezek a platformok támogatottak: %s", "ownCloud %s or higher is required." : "ownCoud %s vagy ennél újabb szükséges.", "ownCloud %s or lower is required." : "ownCoud %s vagy ennél régebbi szükséges.", @@ -26,6 +30,7 @@ OC.L10N.register( "_%n hour ago_::_%n hours ago_" : ["%n órája","%n órája"], "_%n minute ago_::_%n minutes ago_" : ["%n perce","%n perce"], "seconds ago" : "pár másodperce", + "Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "A modul ezzel az azonosítóval:%s nem létezik. Engedélyezd az alkalmazás beállításainál vagy vedd fel a kapcsolatot az adminisztártododdal.", "Empty filename is not allowed" : "Üres fájlnév nem engedétlyezett", "Dot files are not allowed" : "Pontozott fájlok nem engedétlyezettek", "4-byte characters are not supported in file names" : "4-byte karakterek nem támogatottak a fájl nevekben.", @@ -34,15 +39,20 @@ OC.L10N.register( "File name is too long" : "A fájlnév túl hosszú!", "App directory already exists" : "Az alkalmazás mappája már létezik", "Can't create app folder. Please fix permissions. %s" : "Nem lehetett létrehozni az alkalmazás mappáját. Kérem ellenőrizze a jogosultságokat. %s", + "Archive does not contain a directory named %s" : "Az arhívum nem tartalmaz könyvátrat ezzel a névvel %s", "No source specified when installing app" : "Az alkalmazás telepítéséhez nincs forrás megadva", "No href specified when installing app from http" : "Az alkalmazás http-n keresztül történő telepítéséhez nincs href hivetkozás megadva", "No path specified when installing app from local file" : "Az alkalmazás helyi telepítéséhez nincs útvonal (mappa) megadva", "Archives of type %s are not supported" : "A(z) %s típusú tömörített állomány nem támogatott", "Failed to open archive when installing app" : "Nem sikerült megnyitni a tömörített állományt a telepítés során", "App does not provide an info.xml file" : "Az alkalmazás nem szolgáltatott info.xml file-t", + "App cannot be installed because appinfo file cannot be read." : "Az alkalmazást nem telepíthető mert az alkalmazás-infó file nem olvasható.", + "Signature could not get checked. Please contact the app developer and check your admin screen." : "Az aláírás nem ellenőrizhető. Lépj kapcsolatba az alkalmazás fejlesztővel és ellenörízd az admin képernyődet.", "App can't be installed because of not allowed code in the App" : "Az alkalmazást nem lehet telepíteni, mert abban nem engedélyezett programkód szerepel", "App can't be installed because it is not compatible with this version of ownCloud" : "Az alkalmazás nem telepíthető, mert nem kompatibilis az ownCloud jelen verziójával.", "App can't be installed because it contains the true tag which is not allowed for non shipped apps" : "Az alkalmazást nem lehet telepíteni, mert tartalmazza a \n\ntrue\n\ncímkét, ami a nem szállított alkalmazások esetén nem engedélyezett", + "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Az alkalmazást nem telepíthető mert a verzió az info.xml-ben nem azonos azzal amit az alkalmazás boltban van feltüntetve.", + "%s enter the database username and name." : "%s adja meg az adatbázis felhasználó nevét és az adatbázi nevét.", "%s enter the database username." : "%s adja meg az adatbázist elérő felhasználó login nevét.", "%s enter the database name." : "%s adja meg az adatbázis nevét.", "%s you may not use dots in the database name" : "%s az adatbázis neve nem tartalmazhat pontot", @@ -55,6 +65,7 @@ OC.L10N.register( "PostgreSQL username and/or password not valid" : "A PostgreSQL felhasználói név és/vagy jelszó érvénytelen", "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "A Mac OS X nem támogatott és %s nem lesz teljesen működőképes. Csak saját felelősségre használja!", "For the best results, please consider using a GNU/Linux server instead." : "A legjobb eredmény érdekében érdemes GNU/Linux-alapú kiszolgálót használni.", + "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Úgy tűnik, hogy ez a %s példány 32-bites PHP környezetben fut és az open_basedir a php.ini-ben van konfigurálva. A 4GB-nál nagyobb fájlok és problémákhoz vezetnek és nagy akadályt jelentenek.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Kérlek távolítsd el az open_basedir beállítást a php.ini-ből, vagy válts 64bit-es PHP-ra.", "Set an admin username." : "Állítson be egy felhasználói nevet az adminisztrációhoz.", "Set an admin password." : "Állítson be egy jelszót az adminisztrációhoz.", @@ -90,8 +101,10 @@ OC.L10N.register( "Sharing %s failed, because resharing is not allowed" : "%s megosztása nem sikerült, mert a megosztás továbbadása nincs engedélyezve", "Sharing %s failed, because the sharing backend for %s could not find its source" : "%s megosztása nem sikerült, mert %s megosztási alrendszere nem találja", "Sharing %s failed, because the file could not be found in the file cache" : "%s megosztása nem sikerült, mert a fájl nem található a gyorsítótárban", + "Expiration date is in the past" : "Múltbéli lejárati idő.", "Could not find category \"%s\"" : "Ez a kategória nem található: \"%s\"", "Apps" : "Alkalmazások", + "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "A felhasználónévben csak a következő karakterek fordulhatnak elő: \"a-z\", \"A-Z\", \"0-9\", és \"_.@-\"", "A valid username must be provided" : "Érvényes felhasználónevet kell megadnia", "A valid password must be provided" : "Érvényes jelszót kell megadnia", "The username is already being used" : "Ez a bejelentkezési név már foglalt", diff --git a/lib/l10n/hu_HU.json b/lib/l10n/hu_HU.json index e5556782f812b..fbebb566649c5 100644 --- a/lib/l10n/hu_HU.json +++ b/lib/l10n/hu_HU.json @@ -7,8 +7,12 @@ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Úgy tűnik a példakonfigurációt próbálja ténylegesen használni. Ez nem támogatott, és működésképtelenné teheti a telepítést. Kérjük olvassa el a dokumentációt és azt követően változtasson a config.php-n!", "PHP %s or higher is required." : "PHP %s vagy ennél újabb szükséges.", "PHP with a version lower than %s is required." : "Ennél régebbi PHP szükséges: %s.", + "%sbit or higher PHP required." : "%sbit vagy ennél magasabb szükséges.", "Following databases are supported: %s" : "A következő adatbázisok támogatottak: %s", + "The command line tool %s could not be found" : "A parancssori eszköz %s nem található", "The library %s is not available." : "A könyvtár %s nem áll rendelkezésre.", + "Library %s with a version higher than %s is required - available version %s." : "A könyvtár a %s verzióval nagyobb mint a szükséges %s - elérhető verzió %s", + "Library %s with a version lower than %s is required - available version %s." : "A könyvtár a %s verzióval alacsonyabb mint a szükséges %s - elérhető verzió %s", "Following platforms are supported: %s" : "Ezek a platformok támogatottak: %s", "ownCloud %s or higher is required." : "ownCoud %s vagy ennél újabb szükséges.", "ownCloud %s or lower is required." : "ownCoud %s vagy ennél régebbi szükséges.", @@ -24,6 +28,7 @@ "_%n hour ago_::_%n hours ago_" : ["%n órája","%n órája"], "_%n minute ago_::_%n minutes ago_" : ["%n perce","%n perce"], "seconds ago" : "pár másodperce", + "Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "A modul ezzel az azonosítóval:%s nem létezik. Engedélyezd az alkalmazás beállításainál vagy vedd fel a kapcsolatot az adminisztártododdal.", "Empty filename is not allowed" : "Üres fájlnév nem engedétlyezett", "Dot files are not allowed" : "Pontozott fájlok nem engedétlyezettek", "4-byte characters are not supported in file names" : "4-byte karakterek nem támogatottak a fájl nevekben.", @@ -32,15 +37,20 @@ "File name is too long" : "A fájlnév túl hosszú!", "App directory already exists" : "Az alkalmazás mappája már létezik", "Can't create app folder. Please fix permissions. %s" : "Nem lehetett létrehozni az alkalmazás mappáját. Kérem ellenőrizze a jogosultságokat. %s", + "Archive does not contain a directory named %s" : "Az arhívum nem tartalmaz könyvátrat ezzel a névvel %s", "No source specified when installing app" : "Az alkalmazás telepítéséhez nincs forrás megadva", "No href specified when installing app from http" : "Az alkalmazás http-n keresztül történő telepítéséhez nincs href hivetkozás megadva", "No path specified when installing app from local file" : "Az alkalmazás helyi telepítéséhez nincs útvonal (mappa) megadva", "Archives of type %s are not supported" : "A(z) %s típusú tömörített állomány nem támogatott", "Failed to open archive when installing app" : "Nem sikerült megnyitni a tömörített állományt a telepítés során", "App does not provide an info.xml file" : "Az alkalmazás nem szolgáltatott info.xml file-t", + "App cannot be installed because appinfo file cannot be read." : "Az alkalmazást nem telepíthető mert az alkalmazás-infó file nem olvasható.", + "Signature could not get checked. Please contact the app developer and check your admin screen." : "Az aláírás nem ellenőrizhető. Lépj kapcsolatba az alkalmazás fejlesztővel és ellenörízd az admin képernyődet.", "App can't be installed because of not allowed code in the App" : "Az alkalmazást nem lehet telepíteni, mert abban nem engedélyezett programkód szerepel", "App can't be installed because it is not compatible with this version of ownCloud" : "Az alkalmazás nem telepíthető, mert nem kompatibilis az ownCloud jelen verziójával.", "App can't be installed because it contains the true tag which is not allowed for non shipped apps" : "Az alkalmazást nem lehet telepíteni, mert tartalmazza a \n\ntrue\n\ncímkét, ami a nem szállított alkalmazások esetén nem engedélyezett", + "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Az alkalmazást nem telepíthető mert a verzió az info.xml-ben nem azonos azzal amit az alkalmazás boltban van feltüntetve.", + "%s enter the database username and name." : "%s adja meg az adatbázis felhasználó nevét és az adatbázi nevét.", "%s enter the database username." : "%s adja meg az adatbázist elérő felhasználó login nevét.", "%s enter the database name." : "%s adja meg az adatbázis nevét.", "%s you may not use dots in the database name" : "%s az adatbázis neve nem tartalmazhat pontot", @@ -53,6 +63,7 @@ "PostgreSQL username and/or password not valid" : "A PostgreSQL felhasználói név és/vagy jelszó érvénytelen", "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "A Mac OS X nem támogatott és %s nem lesz teljesen működőképes. Csak saját felelősségre használja!", "For the best results, please consider using a GNU/Linux server instead." : "A legjobb eredmény érdekében érdemes GNU/Linux-alapú kiszolgálót használni.", + "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Úgy tűnik, hogy ez a %s példány 32-bites PHP környezetben fut és az open_basedir a php.ini-ben van konfigurálva. A 4GB-nál nagyobb fájlok és problémákhoz vezetnek és nagy akadályt jelentenek.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Kérlek távolítsd el az open_basedir beállítást a php.ini-ből, vagy válts 64bit-es PHP-ra.", "Set an admin username." : "Állítson be egy felhasználói nevet az adminisztrációhoz.", "Set an admin password." : "Állítson be egy jelszót az adminisztrációhoz.", @@ -88,8 +99,10 @@ "Sharing %s failed, because resharing is not allowed" : "%s megosztása nem sikerült, mert a megosztás továbbadása nincs engedélyezve", "Sharing %s failed, because the sharing backend for %s could not find its source" : "%s megosztása nem sikerült, mert %s megosztási alrendszere nem találja", "Sharing %s failed, because the file could not be found in the file cache" : "%s megosztása nem sikerült, mert a fájl nem található a gyorsítótárban", + "Expiration date is in the past" : "Múltbéli lejárati idő.", "Could not find category \"%s\"" : "Ez a kategória nem található: \"%s\"", "Apps" : "Alkalmazások", + "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "A felhasználónévben csak a következő karakterek fordulhatnak elő: \"a-z\", \"A-Z\", \"0-9\", és \"_.@-\"", "A valid username must be provided" : "Érvényes felhasználónevet kell megadnia", "A valid password must be provided" : "Érvényes jelszót kell megadnia", "The username is already being used" : "Ez a bejelentkezési név már foglalt", diff --git a/lib/l10n/sl.js b/lib/l10n/sl.js index 5e0e1fbcdbd53..4a2cc77056cdd 100644 --- a/lib/l10n/sl.js +++ b/lib/l10n/sl.js @@ -143,7 +143,9 @@ OC.L10N.register( "Please ask your server administrator to install the module." : "Obvestite skrbnika strežnika, da je treba namestiti manjkajoč modul.", "PHP module %s not installed." : "Modul PHP %s ni nameščen.", "PHP setting \"%s\" is not set to \"%s\"." : "Nastavitev PHP \"%s\" ni nastavljena na \"%s\".", + "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 mora biti vsaj verzija 2.7.0. Trenutno je nameščena %s.", "To fix this issue update your libxml2 version and restart your web server." : "Za rešitev te težave je treba posodobiti knjižnico libxml2 in nato ponovno zagnati spletni strežnik.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Izgleda, da je PHP nastavljen, da odreže znake v 'inline doc' blokih. To bo povzročilo, da nekateri osnovni moduli ne bodo dosegljivi.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Napako je najverjetneje povzročil predpomnilnik ali pospeševalnik, kot sta Zend OPcache ali eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "Ali so bili moduli PHP nameščeni, pa so še vedno označeni kot manjkajoči?", "Please ask your server administrator to restart the web server." : "Obvestite skrbnika strežnika, da je treba ponovno zagnati spletni strežnik.", diff --git a/lib/l10n/sl.json b/lib/l10n/sl.json index 48c9f69a86dcc..bcb933fa5a306 100644 --- a/lib/l10n/sl.json +++ b/lib/l10n/sl.json @@ -141,7 +141,9 @@ "Please ask your server administrator to install the module." : "Obvestite skrbnika strežnika, da je treba namestiti manjkajoč modul.", "PHP module %s not installed." : "Modul PHP %s ni nameščen.", "PHP setting \"%s\" is not set to \"%s\"." : "Nastavitev PHP \"%s\" ni nastavljena na \"%s\".", + "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 mora biti vsaj verzija 2.7.0. Trenutno je nameščena %s.", "To fix this issue update your libxml2 version and restart your web server." : "Za rešitev te težave je treba posodobiti knjižnico libxml2 in nato ponovno zagnati spletni strežnik.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Izgleda, da je PHP nastavljen, da odreže znake v 'inline doc' blokih. To bo povzročilo, da nekateri osnovni moduli ne bodo dosegljivi.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Napako je najverjetneje povzročil predpomnilnik ali pospeševalnik, kot sta Zend OPcache ali eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "Ali so bili moduli PHP nameščeni, pa so še vedno označeni kot manjkajoči?", "Please ask your server administrator to restart the web server." : "Obvestite skrbnika strežnika, da je treba ponovno zagnati spletni strežnik.", diff --git a/settings/l10n/cs_CZ.js b/settings/l10n/cs_CZ.js index 2485825e0c337..a7a2ef556fce3 100644 --- a/settings/l10n/cs_CZ.js +++ b/settings/l10n/cs_CZ.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Heslo aplikace je přihlašovací údaj umožňující aplikaci nebo přístroji přístup k %s účtu.", "App name" : "Jméno aplikace", "Create new app password" : "Vytvořit nové heslo aplikace", + "Use the credentials below to configure your app or device." : "Použijte níže vypsané přihlašovací údaje k nastavení aplikace nebo přístroje.", "Username" : "Uživatelské jméno", "Done" : "Dokončeno", "Get the apps to sync your files" : "Získat aplikace pro synchronizaci vašich souborů", diff --git a/settings/l10n/cs_CZ.json b/settings/l10n/cs_CZ.json index d4e206bc9fdbe..c192da9d74723 100644 --- a/settings/l10n/cs_CZ.json +++ b/settings/l10n/cs_CZ.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Heslo aplikace je přihlašovací údaj umožňující aplikaci nebo přístroji přístup k %s účtu.", "App name" : "Jméno aplikace", "Create new app password" : "Vytvořit nové heslo aplikace", + "Use the credentials below to configure your app or device." : "Použijte níže vypsané přihlašovací údaje k nastavení aplikace nebo přístroje.", "Username" : "Uživatelské jméno", "Done" : "Dokončeno", "Get the apps to sync your files" : "Získat aplikace pro synchronizaci vašich souborů", diff --git a/settings/l10n/de.js b/settings/l10n/de.js index 029497ea84f43..f3c93cacd84c5 100644 --- a/settings/l10n/de.js +++ b/settings/l10n/de.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Ein App-Passwort ist ein Passwort, dass einer App oder einem Gerät erlaubt auf Ihren %s-Konto zuzugreifen.", "App name" : "App-Name", "Create new app password" : "Neues App-Passwort erstellen", + "Use the credentials below to configure your app or device." : "Verwende die folgenden Zugangsdaten um deine App oder dein Gerät zu konfigurieren.", "Username" : "Benutzername", "Done" : "Erledigt", "Get the apps to sync your files" : "Lade die Apps zur Synchronisierung Deiner Daten herunter", diff --git a/settings/l10n/de.json b/settings/l10n/de.json index 891e031eec091..172c92ac7b351 100644 --- a/settings/l10n/de.json +++ b/settings/l10n/de.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Ein App-Passwort ist ein Passwort, dass einer App oder einem Gerät erlaubt auf Ihren %s-Konto zuzugreifen.", "App name" : "App-Name", "Create new app password" : "Neues App-Passwort erstellen", + "Use the credentials below to configure your app or device." : "Verwende die folgenden Zugangsdaten um deine App oder dein Gerät zu konfigurieren.", "Username" : "Benutzername", "Done" : "Erledigt", "Get the apps to sync your files" : "Lade die Apps zur Synchronisierung Deiner Daten herunter", diff --git a/settings/l10n/fi_FI.js b/settings/l10n/fi_FI.js index 4edc2128ac2ba..a868e8792bac9 100644 --- a/settings/l10n/fi_FI.js +++ b/settings/l10n/fi_FI.js @@ -264,6 +264,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Sovellussalasana on suojakoodi, joka antaa sovellukselle tai laitteelle käyttöoikeuden %s-tiliisi.", "App name" : "Sovelluksen nimi", "Create new app password" : "Luo uusi sovellussalasana", + "Use the credentials below to configure your app or device." : "Käytä alla olevia kirjautumistietoja määrittääksesi sovelluksesi tai laitteen.", "Username" : "Käyttäjätunnus", "Done" : "Valmis", "Get the apps to sync your files" : "Aseta sovellukset synkronoimaan tiedostosi", diff --git a/settings/l10n/fi_FI.json b/settings/l10n/fi_FI.json index 8d7e882579e6d..d62b7f0119299 100644 --- a/settings/l10n/fi_FI.json +++ b/settings/l10n/fi_FI.json @@ -262,6 +262,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Sovellussalasana on suojakoodi, joka antaa sovellukselle tai laitteelle käyttöoikeuden %s-tiliisi.", "App name" : "Sovelluksen nimi", "Create new app password" : "Luo uusi sovellussalasana", + "Use the credentials below to configure your app or device." : "Käytä alla olevia kirjautumistietoja määrittääksesi sovelluksesi tai laitteen.", "Username" : "Käyttäjätunnus", "Done" : "Valmis", "Get the apps to sync your files" : "Aseta sovellukset synkronoimaan tiedostosi", diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js index ad98f51acfa56..de42c29cd6efb 100644 --- a/settings/l10n/fr.js +++ b/settings/l10n/fr.js @@ -118,6 +118,8 @@ OC.L10N.register( "__language_name__" : "Français", "Unlimited" : "Illimité", "Personal info" : "Informations personnelles", + "Sessions" : "Sessions", + "App passwords" : "Mots de passe d'applications", "Sync clients" : "Clients de synchronisation", "Everything (fatal issues, errors, warnings, info, debug)" : "Tout (erreurs fatales, erreurs, avertissements, informations, debogage)", "Info, warnings, errors and fatal issues" : "Informations, avertissements, erreurs et erreurs fatales", @@ -135,6 +137,7 @@ OC.L10N.register( "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "La configuration est en mode lecture seule. Ceci empêche la modification de certaines configurations via l'interface web. De plus, le fichier doit être passé manuellement en lecture-écriture avant chaque mise à jour.", "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "PHP est apparemment configuré pour supprimer les blocs de documentation internes. Cela rendra plusieurs applications de base inaccessibles.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "La raison est probablement l'utilisation d'un cache / accélérateur tel que Zend OPcache ou eAccelerator.", + "Your database does not run with \"READ COMMITED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "Votre base de données n'est pas lancée avec le niveau d'isolation de transaction \"READ COMMITED\". Cela peut causer des problèmes lorsque plusieurs actions sont lancées parallèlement.", "Your server is running on Microsoft Windows. We highly recommend Linux for optimal user experience." : "Votre serveur fonctionne actuellement sur une plateforme Microsoft Windows. Nous vous recommandons fortement d'utiliser une plateforme Linux pour une expérience utilisateur optimale.", "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "Une version de %1$s plus ancienne que %2$s est installée. Pour améliorer la stabilité et les performances, nous recommandons de mettre %1$s à jour.", "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "Le module PHP 'fileinfo' est manquant. Il est vivement recommandé de l'activer afin d'obtenir de meilleurs résultats de détection mime-type.", @@ -271,7 +274,12 @@ OC.L10N.register( "These are the web, desktop and mobile clients currently logged in to your ownCloud." : "Voici les clients web, de bureau et mobiles actuellement connectés à votre ownCloud.", "Browser" : "Navigateur", "Most recent activity" : "Activité la plus récente", + "You've linked these apps." : "Vous avez lié ces applications.", "Name" : "Nom", + "An app password is a passcode that gives an app or device permissions to access your %s account." : "Un mot de passe d'une application est un code d'accès qui donne à une application ou à un appareil les droits d'accès à votre compte %s.", + "App name" : "Nom de l'application", + "Create new app password" : "Créer un nouveau mot de passe d'application", + "Use the credentials below to configure your app or device." : "Utilisez les identifiants ci-dessous pour configurer votre application ou votre périphérique.", "Username" : "Nom d'utilisateur", "Done" : "Terminé", "Get the apps to sync your files" : "Obtenez les applications de synchronisation de vos fichiers", diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json index fe130ae13596d..21cbbd2c940ab 100644 --- a/settings/l10n/fr.json +++ b/settings/l10n/fr.json @@ -116,6 +116,8 @@ "__language_name__" : "Français", "Unlimited" : "Illimité", "Personal info" : "Informations personnelles", + "Sessions" : "Sessions", + "App passwords" : "Mots de passe d'applications", "Sync clients" : "Clients de synchronisation", "Everything (fatal issues, errors, warnings, info, debug)" : "Tout (erreurs fatales, erreurs, avertissements, informations, debogage)", "Info, warnings, errors and fatal issues" : "Informations, avertissements, erreurs et erreurs fatales", @@ -133,6 +135,7 @@ "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "La configuration est en mode lecture seule. Ceci empêche la modification de certaines configurations via l'interface web. De plus, le fichier doit être passé manuellement en lecture-écriture avant chaque mise à jour.", "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "PHP est apparemment configuré pour supprimer les blocs de documentation internes. Cela rendra plusieurs applications de base inaccessibles.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "La raison est probablement l'utilisation d'un cache / accélérateur tel que Zend OPcache ou eAccelerator.", + "Your database does not run with \"READ COMMITED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "Votre base de données n'est pas lancée avec le niveau d'isolation de transaction \"READ COMMITED\". Cela peut causer des problèmes lorsque plusieurs actions sont lancées parallèlement.", "Your server is running on Microsoft Windows. We highly recommend Linux for optimal user experience." : "Votre serveur fonctionne actuellement sur une plateforme Microsoft Windows. Nous vous recommandons fortement d'utiliser une plateforme Linux pour une expérience utilisateur optimale.", "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "Une version de %1$s plus ancienne que %2$s est installée. Pour améliorer la stabilité et les performances, nous recommandons de mettre %1$s à jour.", "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "Le module PHP 'fileinfo' est manquant. Il est vivement recommandé de l'activer afin d'obtenir de meilleurs résultats de détection mime-type.", @@ -269,7 +272,12 @@ "These are the web, desktop and mobile clients currently logged in to your ownCloud." : "Voici les clients web, de bureau et mobiles actuellement connectés à votre ownCloud.", "Browser" : "Navigateur", "Most recent activity" : "Activité la plus récente", + "You've linked these apps." : "Vous avez lié ces applications.", "Name" : "Nom", + "An app password is a passcode that gives an app or device permissions to access your %s account." : "Un mot de passe d'une application est un code d'accès qui donne à une application ou à un appareil les droits d'accès à votre compte %s.", + "App name" : "Nom de l'application", + "Create new app password" : "Créer un nouveau mot de passe d'application", + "Use the credentials below to configure your app or device." : "Utilisez les identifiants ci-dessous pour configurer votre application ou votre périphérique.", "Username" : "Nom d'utilisateur", "Done" : "Terminé", "Get the apps to sync your files" : "Obtenez les applications de synchronisation de vos fichiers", diff --git a/settings/l10n/he.js b/settings/l10n/he.js index 311e6e898b9a3..fe936e895621b 100644 --- a/settings/l10n/he.js +++ b/settings/l10n/he.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "סיסמת יישום הנה קוד סיסמא שמאפשרת ליישום או התקן הרשאות גישה לחשבון %s שלך.", "App name" : "שם יישום", "Create new app password" : "יצירת סיסמת יישום חדשה", + "Use the credentials below to configure your app or device." : "יש להשתמש באישורים מטה להגדרת היישום או ההתקן שלך.", "Username" : "שם משתמש", "Done" : "הסתיים", "Get the apps to sync your files" : "קבלת היישומים לסנכרון הקבצים שלך", diff --git a/settings/l10n/he.json b/settings/l10n/he.json index 54de8555fca4e..7f1a1c69500bb 100644 --- a/settings/l10n/he.json +++ b/settings/l10n/he.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "סיסמת יישום הנה קוד סיסמא שמאפשרת ליישום או התקן הרשאות גישה לחשבון %s שלך.", "App name" : "שם יישום", "Create new app password" : "יצירת סיסמת יישום חדשה", + "Use the credentials below to configure your app or device." : "יש להשתמש באישורים מטה להגדרת היישום או ההתקן שלך.", "Username" : "שם משתמש", "Done" : "הסתיים", "Get the apps to sync your files" : "קבלת היישומים לסנכרון הקבצים שלך", diff --git a/settings/l10n/it.js b/settings/l10n/it.js index 6104c0bf3eb3b..8e14b48f25916 100644 --- a/settings/l10n/it.js +++ b/settings/l10n/it.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Una password di applicazione è un codice di sicurezza che fornisce a un'applicazione o a un dispositivo i permessi per accedere al tuo account %s.", "App name" : "Nome applicazione", "Create new app password" : "Crea nuova password di applicazione", + "Use the credentials below to configure your app or device." : "Usa le credenziali seguenti per configurare l'applicazione o il dispositivo.", "Username" : "Nome utente", "Done" : "Completato", "Get the apps to sync your files" : "Scarica le applicazioni per sincronizzare i tuoi file", diff --git a/settings/l10n/it.json b/settings/l10n/it.json index f0fac257c4bdf..1fe431765c332 100644 --- a/settings/l10n/it.json +++ b/settings/l10n/it.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Una password di applicazione è un codice di sicurezza che fornisce a un'applicazione o a un dispositivo i permessi per accedere al tuo account %s.", "App name" : "Nome applicazione", "Create new app password" : "Crea nuova password di applicazione", + "Use the credentials below to configure your app or device." : "Usa le credenziali seguenti per configurare l'applicazione o il dispositivo.", "Username" : "Nome utente", "Done" : "Completato", "Get the apps to sync your files" : "Scarica le applicazioni per sincronizzare i tuoi file", diff --git a/settings/l10n/nl.js b/settings/l10n/nl.js index 800ae67042812..b9036f53b8317 100644 --- a/settings/l10n/nl.js +++ b/settings/l10n/nl.js @@ -119,6 +119,7 @@ OC.L10N.register( "Unlimited" : "Ongelimiteerd", "Personal info" : "Persoonlijke info", "Sessions" : "Sessies", + "App passwords" : "App wachtwoorden", "Sync clients" : "Sync clients", "Everything (fatal issues, errors, warnings, info, debug)" : "Alles (fatale problemen, fouten, waarschuwingen, info, debug)", "Info, warnings, errors and fatal issues" : "Info, waarschuwingen, fouten en fatale problemen", @@ -273,7 +274,10 @@ OC.L10N.register( "These are the web, desktop and mobile clients currently logged in to your ownCloud." : "Dit zijn de web, desktop en mobiele clients die momenteel zijn verbonden met uw ownCloud.", "Browser" : "Browser", "Most recent activity" : "Meest recente activiteit", + "You've linked these apps." : "U hebt deze apps gelinkt.", "Name" : "Naam", + "App name" : "App naam", + "Create new app password" : "Creëer nieuw app wachtwoord", "Username" : "Gebruikersnaam", "Done" : "Gedaan", "Get the apps to sync your files" : "Download de apps om bestanden te synchroniseren", diff --git a/settings/l10n/nl.json b/settings/l10n/nl.json index 660e4acce5851..474e657f320dc 100644 --- a/settings/l10n/nl.json +++ b/settings/l10n/nl.json @@ -117,6 +117,7 @@ "Unlimited" : "Ongelimiteerd", "Personal info" : "Persoonlijke info", "Sessions" : "Sessies", + "App passwords" : "App wachtwoorden", "Sync clients" : "Sync clients", "Everything (fatal issues, errors, warnings, info, debug)" : "Alles (fatale problemen, fouten, waarschuwingen, info, debug)", "Info, warnings, errors and fatal issues" : "Info, waarschuwingen, fouten en fatale problemen", @@ -271,7 +272,10 @@ "These are the web, desktop and mobile clients currently logged in to your ownCloud." : "Dit zijn de web, desktop en mobiele clients die momenteel zijn verbonden met uw ownCloud.", "Browser" : "Browser", "Most recent activity" : "Meest recente activiteit", + "You've linked these apps." : "U hebt deze apps gelinkt.", "Name" : "Naam", + "App name" : "App naam", + "Create new app password" : "Creëer nieuw app wachtwoord", "Username" : "Gebruikersnaam", "Done" : "Gedaan", "Get the apps to sync your files" : "Download de apps om bestanden te synchroniseren", diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js index 824f6f741722a..9c666219e9873 100644 --- a/settings/l10n/ru.js +++ b/settings/l10n/ru.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Пароль приложения представляет собой код доступа, который дает приложению или устройству разрешения на доступ к вашему аккаунту %s.", "App name" : "Название приложения", "Create new app password" : "Создать новый пароль для приложения", + "Use the credentials below to configure your app or device." : "Используйте учётные данные ниже, чтобы настроить ваше приложение или устройство.", "Username" : "Имя пользователя", "Done" : "Выполнено", "Get the apps to sync your files" : "Получить приложения для синхронизации ваших файлов", diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json index 7a84ef3547541..bb9debee62693 100644 --- a/settings/l10n/ru.json +++ b/settings/l10n/ru.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Пароль приложения представляет собой код доступа, который дает приложению или устройству разрешения на доступ к вашему аккаунту %s.", "App name" : "Название приложения", "Create new app password" : "Создать новый пароль для приложения", + "Use the credentials below to configure your app or device." : "Используйте учётные данные ниже, чтобы настроить ваше приложение или устройство.", "Username" : "Имя пользователя", "Done" : "Выполнено", "Get the apps to sync your files" : "Получить приложения для синхронизации ваших файлов", diff --git a/settings/l10n/sl.js b/settings/l10n/sl.js index fb5bacf721ee1..57ae1eaac4ce8 100644 --- a/settings/l10n/sl.js +++ b/settings/l10n/sl.js @@ -70,6 +70,7 @@ OC.L10N.register( "Disable" : "Onemogoči", "Enable" : "Omogoči", "Error while enabling app" : "Napaka omogočanja programa", + "Error: this app cannot be enabled because it makes the server unstable" : "Napaka: ta aplikacija ne more biti aktivna, ker povzroča nestabilnost strežnika", "Error: could not disable broken app" : "Napaka: ni mogoče onemogočiti okvarjenega programa", "Error while disabling broken app" : "Napaka onemogočanja okvarjenega programa", "Updating...." : "Poteka posodabljanje ...", @@ -82,6 +83,9 @@ OC.L10N.register( "App update" : "Posodabljanje vstavkov", "No apps found for {query}" : "Ni programov, skladnih z nizom \"{query}\".", "Disconnect" : "Prekinjeni povezavo", + "Error while loading browser sessions and device tokens" : "Napaka med nalaganjem brskalnika in ključev naprave", + "Error while creating device token" : "Napaka med izdelavo ključa naprave", + "Error while deleting the token" : "Napaka med brisanjem ključa", "An error occurred. Please upload an ASCII-encoded PEM certificate." : "Prišlo je do napake. Uvoziti je treba ustrezno ASCII kodirano potrdilo PEM.", "Valid until {date}" : "Veljavno do {date}", "Delete" : "Izbriši", @@ -111,6 +115,7 @@ OC.L10N.register( "Unlimited" : "Neomejeno", "Personal info" : "Osebni podatki", "Sessions" : "Seje", + "App passwords" : "Gesla aplikacije", "Sync clients" : "Uskladi odjemalce", "Everything (fatal issues, errors, warnings, info, debug)" : "Vse (podrobnosti, opozorila, hrošče, napake in usodne dogodke)", "Info, warnings, errors and fatal issues" : "Podrobnosti, opozorila, napake in usodne dogodke", @@ -145,12 +150,16 @@ OC.L10N.register( "Allow users to send mail notification for shared files to other users" : "Dovoli uporabnikom pošiljanje obvestil o souporabi datotek z drugimi uporabniki.", "Exclude groups from sharing" : "Izloči skupine iz souporabe", "These groups will still be able to receive shares, but not to initiate them." : "Te skupine lahko sprejemajo mape v souporabo, ne morejo pa souporabe dovoliti", + "Last cron job execution: %s." : "Zadnje periodično opravilo: %s.", + "Last cron job execution: %s. Something seems wrong." : "Zadnje periodično opravilo: %s. Nekaj izgleda narobe.", "Cron was not executed yet!" : "Periodično opravilo cron še ni zagnano!", "Execute one task with each page loaded" : "Izvedi eno nalogo z vsako naloženo stranjo.", "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "Datoteka cron.php je vpisana za periodično opravilo webcron za potrditev sklica vsakih 15 minut pri povezavi preko HTTP.", "Use system's cron service to call the cron.php file every 15 minutes." : "Uporabi storitev periodičnih opravil za klic datoteke cron.php vsakih 15 minut.", "Enable server-side encryption" : "Omogoči šifriranje na strežniku", "Please read carefully before activating server-side encryption: " : "Pozorno preberite opombe, preden omogočite strežniško šifriranje:", + "Be aware that encryption always increases the file size." : "Upoštevajte, da šifriranje vedno poveča velikost datoteke.", + "This is the final warning: Do you really want to enable encryption?" : "To je zadnje opozorilo. Ali resnično želite vključiti šifriranje?", "Enable encryption" : "Omogoči šifriranje", "Select default encryption module:" : "Izbor privzetega modula za šifriranje:", "Start migration" : "Začni selitev", @@ -189,6 +198,7 @@ OC.L10N.register( "Documentation:" : "Dokumentacija:", "User documentation" : "Uporabniška dokumentacija", "Admin documentation" : "Skrbniška dokumentacija", + "Visit website" : "Obiščite spletno stran", "Report a bug" : "Pošlji poročilo o hrošču", "Show description …" : "Pokaži opis ...", "Hide description …" : "Skrij opis ...", @@ -217,6 +227,7 @@ OC.L10N.register( "Select from Files" : "Izbor iz datotek", "Remove image" : "Odstrani sliko", "png or jpg, max. 20 MB" : "png ali jpg, največ. 20 MB", + "Picture provided by original account" : "Slika iz izvornega računa", "Cancel" : "Prekliči", "Choose as profile picture" : "Izberi kot sliko profila", "Full name" : "Polno ime", @@ -235,7 +246,10 @@ OC.L10N.register( "Help translate" : "Sodelujte pri prevajanju", "Browser" : "Brskalnik", "Most recent activity" : "Zadnja dejavnost", + "You've linked these apps." : "Vi ste povezali te aplikacije.", "Name" : "Ime", + "App name" : "Naziv aplikacije", + "Create new app password" : "Ustvari novo geslo aplikacije", "Username" : "Uporabniško ime", "Done" : "Končano", "Get the apps to sync your files" : "Pridobi programe za usklajevanje datotek", diff --git a/settings/l10n/sl.json b/settings/l10n/sl.json index 495206d568e32..9d8dfa0652df7 100644 --- a/settings/l10n/sl.json +++ b/settings/l10n/sl.json @@ -68,6 +68,7 @@ "Disable" : "Onemogoči", "Enable" : "Omogoči", "Error while enabling app" : "Napaka omogočanja programa", + "Error: this app cannot be enabled because it makes the server unstable" : "Napaka: ta aplikacija ne more biti aktivna, ker povzroča nestabilnost strežnika", "Error: could not disable broken app" : "Napaka: ni mogoče onemogočiti okvarjenega programa", "Error while disabling broken app" : "Napaka onemogočanja okvarjenega programa", "Updating...." : "Poteka posodabljanje ...", @@ -80,6 +81,9 @@ "App update" : "Posodabljanje vstavkov", "No apps found for {query}" : "Ni programov, skladnih z nizom \"{query}\".", "Disconnect" : "Prekinjeni povezavo", + "Error while loading browser sessions and device tokens" : "Napaka med nalaganjem brskalnika in ključev naprave", + "Error while creating device token" : "Napaka med izdelavo ključa naprave", + "Error while deleting the token" : "Napaka med brisanjem ključa", "An error occurred. Please upload an ASCII-encoded PEM certificate." : "Prišlo je do napake. Uvoziti je treba ustrezno ASCII kodirano potrdilo PEM.", "Valid until {date}" : "Veljavno do {date}", "Delete" : "Izbriši", @@ -109,6 +113,7 @@ "Unlimited" : "Neomejeno", "Personal info" : "Osebni podatki", "Sessions" : "Seje", + "App passwords" : "Gesla aplikacije", "Sync clients" : "Uskladi odjemalce", "Everything (fatal issues, errors, warnings, info, debug)" : "Vse (podrobnosti, opozorila, hrošče, napake in usodne dogodke)", "Info, warnings, errors and fatal issues" : "Podrobnosti, opozorila, napake in usodne dogodke", @@ -143,12 +148,16 @@ "Allow users to send mail notification for shared files to other users" : "Dovoli uporabnikom pošiljanje obvestil o souporabi datotek z drugimi uporabniki.", "Exclude groups from sharing" : "Izloči skupine iz souporabe", "These groups will still be able to receive shares, but not to initiate them." : "Te skupine lahko sprejemajo mape v souporabo, ne morejo pa souporabe dovoliti", + "Last cron job execution: %s." : "Zadnje periodično opravilo: %s.", + "Last cron job execution: %s. Something seems wrong." : "Zadnje periodično opravilo: %s. Nekaj izgleda narobe.", "Cron was not executed yet!" : "Periodično opravilo cron še ni zagnano!", "Execute one task with each page loaded" : "Izvedi eno nalogo z vsako naloženo stranjo.", "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "Datoteka cron.php je vpisana za periodično opravilo webcron za potrditev sklica vsakih 15 minut pri povezavi preko HTTP.", "Use system's cron service to call the cron.php file every 15 minutes." : "Uporabi storitev periodičnih opravil za klic datoteke cron.php vsakih 15 minut.", "Enable server-side encryption" : "Omogoči šifriranje na strežniku", "Please read carefully before activating server-side encryption: " : "Pozorno preberite opombe, preden omogočite strežniško šifriranje:", + "Be aware that encryption always increases the file size." : "Upoštevajte, da šifriranje vedno poveča velikost datoteke.", + "This is the final warning: Do you really want to enable encryption?" : "To je zadnje opozorilo. Ali resnično želite vključiti šifriranje?", "Enable encryption" : "Omogoči šifriranje", "Select default encryption module:" : "Izbor privzetega modula za šifriranje:", "Start migration" : "Začni selitev", @@ -187,6 +196,7 @@ "Documentation:" : "Dokumentacija:", "User documentation" : "Uporabniška dokumentacija", "Admin documentation" : "Skrbniška dokumentacija", + "Visit website" : "Obiščite spletno stran", "Report a bug" : "Pošlji poročilo o hrošču", "Show description …" : "Pokaži opis ...", "Hide description …" : "Skrij opis ...", @@ -215,6 +225,7 @@ "Select from Files" : "Izbor iz datotek", "Remove image" : "Odstrani sliko", "png or jpg, max. 20 MB" : "png ali jpg, največ. 20 MB", + "Picture provided by original account" : "Slika iz izvornega računa", "Cancel" : "Prekliči", "Choose as profile picture" : "Izberi kot sliko profila", "Full name" : "Polno ime", @@ -233,7 +244,10 @@ "Help translate" : "Sodelujte pri prevajanju", "Browser" : "Brskalnik", "Most recent activity" : "Zadnja dejavnost", + "You've linked these apps." : "Vi ste povezali te aplikacije.", "Name" : "Ime", + "App name" : "Naziv aplikacije", + "Create new app password" : "Ustvari novo geslo aplikacije", "Username" : "Uporabniško ime", "Done" : "Končano", "Get the apps to sync your files" : "Pridobi programe za usklajevanje datotek", diff --git a/settings/l10n/sq.js b/settings/l10n/sq.js index f2e96691e23ed..302f2f7ebc971 100644 --- a/settings/l10n/sq.js +++ b/settings/l10n/sq.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "Fjalëkalimet e aplikacioneve janë kodkalime që u japin leje një aplikacioni ose pajisjeje të hyjnë në llogarinë tuaj %s.", "App name" : "Emër aplikacioni", "Create new app password" : "Krijoni fjalëkalim aplikacioni të ri", + "Use the credentials below to configure your app or device." : "Përdorni kredencialet më poshtë për të formësuar aplikacionin apo pajisjen tuaj.", "Username" : "Emër përdoruesi", "Done" : "U bë", "Get the apps to sync your files" : "Merrni aplikacionet për njëkohësim të kartelave tuaja", diff --git a/settings/l10n/sq.json b/settings/l10n/sq.json index 812a3f5dc1309..5ec0798b2f3aa 100644 --- a/settings/l10n/sq.json +++ b/settings/l10n/sq.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "Fjalëkalimet e aplikacioneve janë kodkalime që u japin leje një aplikacioni ose pajisjeje të hyjnë në llogarinë tuaj %s.", "App name" : "Emër aplikacioni", "Create new app password" : "Krijoni fjalëkalim aplikacioni të ri", + "Use the credentials below to configure your app or device." : "Përdorni kredencialet më poshtë për të formësuar aplikacionin apo pajisjen tuaj.", "Username" : "Emër përdoruesi", "Done" : "U bë", "Get the apps to sync your files" : "Merrni aplikacionet për njëkohësim të kartelave tuaja", From d2209d304f1bb645c38841a14e21afb18bfc0ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 29 Jun 2016 12:13:59 +0200 Subject: [PATCH 42/81] get only vcards which match both the address book id and the vcard uri (#25294) --- apps/dav/lib/CardDAV/CardDavBackend.php | 2 +- apps/dav/tests/unit/CardDAV/CardDavBackendTest.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 2ad9f4778c927..39f76a4b42065 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -848,7 +848,7 @@ public function getContact($addressBookId, $uri) { $query = $this->db->getQueryBuilder(); $query->select('*')->from($this->dbCardsTable) ->where($query->expr()->eq('uri', $query->createNamedParameter($uri))) - ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); + ->andWhere($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); $queryResult = $query->execute(); $contact = $queryResult->fetch(); $queryResult->closeCursor(); diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index 58a93befe681f..203d4512a4758 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -606,6 +606,10 @@ public function testGetContact() { $this->assertSame(5489543, (int)$result['lastmodified']); $this->assertSame('etag0', $result['etag']); $this->assertSame(120, (int)$result['size']); + + // this shouldn't return any result because 'uri1' is in address book 1 + $result = $this->backend->getContact(0, 'uri1'); + $this->assertEmpty($result); } public function testGetContactFail() { From 2be978c3a0bba646ad3104bfe1d9937ea18cff86 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 29 Jun 2016 14:36:30 +0200 Subject: [PATCH 43/81] Update transifex config --- l10n/.tx/config | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/l10n/.tx/config b/l10n/.tx/config index acb2daec6c793..78f1cae978c23 100644 --- a/l10n/.tx/config +++ b/l10n/.tx/config @@ -2,93 +2,92 @@ host = https://www.transifex.com lang_map = ja_JP: ja -[owncloud.core] +[nextcloud.core] file_filter = /core.po source_file = templates/core.pot source_lang = en type = PO -[owncloud.files] +[nextcloud.files] file_filter = /files.po source_file = templates/files.pot source_lang = en type = PO -[owncloud.settings-1] +[nextcloud.settings-1] file_filter = /settings.po source_file = templates/settings.pot source_lang = en type = PO -[owncloud.lib] +[nextcloud.lib] file_filter = /lib.po source_file = templates/lib.pot source_lang = en type = PO -[owncloud.files_encryption] +[nextcloud.files_encryption] file_filter = /encryption.po source_file = templates/encryption.pot source_lang = en type = PO -[owncloud.files_external] +[nextcloud.files_external] file_filter = /files_external.po source_file = templates/files_external.pot source_lang = en type = PO -[owncloud.files_sharing] +[nextcloud.files_sharing] file_filter = /files_sharing.po source_file = templates/files_sharing.pot source_lang = en type = PO -[owncloud.files_trashbin] +[nextcloud.files_trashbin] file_filter = /files_trashbin.po source_file = templates/files_trashbin.pot source_lang = en type = PO -[owncloud.files_versions] +[nextcloud.files_versions] file_filter = /files_versions.po source_file = templates/files_versions.pot source_lang = en type = PO -[owncloud.user_ldap] +[nextcloud.user_ldap] file_filter = /user_ldap.po source_file = templates/user_ldap.pot source_lang = en type = PO -[owncloud.comments] +[nextcloud.comments] file_filter = /comments.po source_file = templates/comments.pot source_lang = en type = PO -[owncloud.federatedfilesharing] +[nextcloud.federatedfilesharing] file_filter = /federatedfilesharing.po source_file = templates/federatedfilesharing.pot source_lang = en type = PO -[owncloud.federation] +[nextcloud.federation] file_filter = /federation.po source_file = templates/federation.pot source_lang = en type = PO -[owncloud.systemtags] +[nextcloud.systemtags] file_filter = /systemtags.po source_file = templates/systemtags.pot source_lang = en type = PO -[owncloud.updatenotification] +[nextcloud.updatenotification] file_filter = /updatenotification.po source_file = templates/updatenotification.pot source_lang = en type = PO - From fe007fd5435d41ecc6ad5f307d684d030bdff3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 29 Jun 2016 14:54:41 +0200 Subject: [PATCH 44/81] Various database migration fixes (#25209) * String columns with a length higher then 4000 are converted into a CLOB columns automagically - we have to respect this when migrating * Adding schema migration tests to prevent unnecessary and non-sense migration steps Fix Oracle autoincrement and unsigned handling * Fix sqlite integer type for autoincrement * Use lower case table names - fixes pg * Fix postgres with default -1 - this only affect pg 9.4 servers - 9.5 seems to work fine --- lib/private/DB/MDB2SchemaManager.php | 2 +- lib/private/DB/Migrator.php | 20 + lib/private/DB/OracleMigrator.php | 6 + lib/private/DB/PostgreSqlMigrator.php | 55 + lib/private/DB/SQLiteMigrator.php | 11 + tests/lib/DB/DBSchemaTest.php | 7 +- tests/lib/DB/SchemaDiffTest.php | 99 ++ tests/lib/DB/schemDiffData/autoincrement.xml | 16 + tests/lib/DB/schemDiffData/clob.xml | 14 + tests/lib/DB/schemDiffData/core.xml | 1347 ++++++++++++++++++ tests/lib/DB/schemDiffData/default-1.xml | 51 + tests/lib/DB/schemDiffData/unsigned.xml | 68 + 12 files changed, 1692 insertions(+), 4 deletions(-) create mode 100644 lib/private/DB/PostgreSqlMigrator.php create mode 100644 tests/lib/DB/SchemaDiffTest.php create mode 100644 tests/lib/DB/schemDiffData/autoincrement.xml create mode 100644 tests/lib/DB/schemDiffData/clob.xml create mode 100644 tests/lib/DB/schemDiffData/core.xml create mode 100644 tests/lib/DB/schemDiffData/default-1.xml create mode 100644 tests/lib/DB/schemDiffData/unsigned.xml diff --git a/lib/private/DB/MDB2SchemaManager.php b/lib/private/DB/MDB2SchemaManager.php index 1d25ae9f18c0a..79811d8c6cd5a 100644 --- a/lib/private/DB/MDB2SchemaManager.php +++ b/lib/private/DB/MDB2SchemaManager.php @@ -84,7 +84,7 @@ public function getMigrator() { } else if ($platform instanceof MySqlPlatform) { return new MySQLMigrator($this->conn, $random, $config, $dispatcher); } else if ($platform instanceof PostgreSqlPlatform) { - return new Migrator($this->conn, $random, $config, $dispatcher); + return new PostgreSqlMigrator($this->conn, $random, $config, $dispatcher); } else { return new NoCheckMigrator($this->conn, $random, $config, $dispatcher); } diff --git a/lib/private/DB/Migrator.php b/lib/private/DB/Migrator.php index 8b8a34d98657d..f2efd6916d7d1 100644 --- a/lib/private/DB/Migrator.php +++ b/lib/private/DB/Migrator.php @@ -33,6 +33,8 @@ use \Doctrine\DBAL\Schema\Schema; use \Doctrine\DBAL\Schema\SchemaConfig; use \Doctrine\DBAL\Schema\Comparator; +use Doctrine\DBAL\Types\StringType; +use Doctrine\DBAL\Types\Type; use OCP\IConfig; use OCP\Security\ISecureRandom; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -194,7 +196,25 @@ protected function renameTableSchema(Table $table, $newName) { return new Table($newName, $table->getColumns(), $newIndexes, array(), 0, $table->getOptions()); } + /** + * @param Schema $targetSchema + * @param \Doctrine\DBAL\Connection $connection + * @return \Doctrine\DBAL\Schema\SchemaDiff + * @throws DBALException + */ protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) { + // adjust varchar columns with a length higher then getVarcharMaxLength to clob + foreach ($targetSchema->getTables() as $table) { + foreach ($table->getColumns() as $column) { + if ($column->getType() instanceof StringType) { + if ($column->getLength() > $connection->getDatabasePlatform()->getVarcharMaxLength()) { + $column->setType(Type::getType('text')); + $column->setLength(null); + } + } + } + } + $filterExpression = $this->getFilterExpression(); $this->connection->getConfiguration()-> setFilterSchemaAssetsExpression($filterExpression); diff --git a/lib/private/DB/OracleMigrator.php b/lib/private/DB/OracleMigrator.php index ceb89cf64d43c..010f9213a1d9e 100644 --- a/lib/private/DB/OracleMigrator.php +++ b/lib/private/DB/OracleMigrator.php @@ -23,6 +23,7 @@ namespace OC\DB; +use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\Schema; class OracleMigrator extends NoCheckMigrator { @@ -39,7 +40,12 @@ protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $conn $tableDiff->name = $this->connection->quoteIdentifier($tableDiff->name); foreach ($tableDiff->changedColumns as $column) { $column->oldColumnName = $this->connection->quoteIdentifier($column->oldColumnName); + // auto increment is not relevant for oracle and can anyhow not be applied on change + $column->changedProperties = array_diff($column->changedProperties, ['autoincrement', 'unsigned']); } + $tableDiff->changedColumns = array_filter($tableDiff->changedColumns, function (ColumnDiff $column) { + return count($column->changedProperties) > 0; + }); } return $schemaDiff; diff --git a/lib/private/DB/PostgreSqlMigrator.php b/lib/private/DB/PostgreSqlMigrator.php new file mode 100644 index 0000000000000..75e6e0a16c91d --- /dev/null +++ b/lib/private/DB/PostgreSqlMigrator.php @@ -0,0 +1,55 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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 + * + */ + +namespace OC\DB; + +use Doctrine\DBAL\Schema\Schema; + +class PostgreSqlMigrator extends Migrator { + /** + * @param Schema $targetSchema + * @param \Doctrine\DBAL\Connection $connection + * @return \Doctrine\DBAL\Schema\SchemaDiff + */ + protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) { + $schemaDiff = parent::getDiff($targetSchema, $connection); + + foreach ($schemaDiff->changedTables as $tableDiff) { + // fix default value in brackets - pg 9.4 is returning a negative default value in () + // see https://github.com/doctrine/dbal/issues/2427 + foreach ($tableDiff->changedColumns as $column) { + $column->changedProperties = array_filter($column->changedProperties, function ($changedProperties) use ($column) { + if ($changedProperties !== 'default') { + return true; + } + $fromDefault = $column->fromColumn->getDefault(); + $toDefault = $column->column->getDefault(); + $fromDefault = trim($fromDefault, "()"); + + // by intention usage of != + return $fromDefault != $toDefault; + }); + } + } + + return $schemaDiff; + } +} diff --git a/lib/private/DB/SQLiteMigrator.php b/lib/private/DB/SQLiteMigrator.php index 8ea325810118c..837a3a2987ff8 100644 --- a/lib/private/DB/SQLiteMigrator.php +++ b/lib/private/DB/SQLiteMigrator.php @@ -26,6 +26,8 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Types\BigIntType; +use Doctrine\DBAL\Types\Type; class SQLiteMigrator extends Migrator { @@ -76,6 +78,15 @@ protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $conn $platform->registerDoctrineTypeMapping('smallint unsigned', 'integer'); $platform->registerDoctrineTypeMapping('varchar ', 'string'); + // with sqlite autoincrement columns is of type integer + foreach ($targetSchema->getTables() as $table) { + foreach ($table->getColumns() as $column) { + if ($column->getType() instanceof BigIntType && $column->getAutoincrement()) { + $column->setType(Type::getType('integer')); + } + } + } + return parent::getDiff($targetSchema, $connection); } } diff --git a/tests/lib/DB/DBSchemaTest.php b/tests/lib/DB/DBSchemaTest.php index 284fc532c2add..ba17546a34a15 100644 --- a/tests/lib/DB/DBSchemaTest.php +++ b/tests/lib/DB/DBSchemaTest.php @@ -8,15 +8,17 @@ namespace Test\DB; +use Doctrine\DBAL\Platforms\SqlitePlatform; use OC_DB; use OCP\Security\ISecureRandom; +use Test\TestCase; /** * Class DBSchemaTest * * @group DB */ -class DBSchemaTest extends \Test\TestCase { +class DBSchemaTest extends TestCase { protected $schema_file = 'static://test_db_scheme'; protected $schema_file2 = 'static://test_db_scheme2'; protected $table1; @@ -53,7 +55,6 @@ protected function tearDown() { * @medium */ public function testSchema() { - $platform = \OC::$server->getDatabaseConnection()->getDatabasePlatform(); $this->doTestSchemaCreating(); $this->doTestSchemaChanging(); $this->doTestSchemaDumping(); @@ -97,7 +98,7 @@ public function assertTableExist($table) { */ public function assertTableNotExist($table) { $platform = \OC::$server->getDatabaseConnection()->getDatabasePlatform(); - if ($platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) { + if ($platform instanceof SqlitePlatform) { // sqlite removes the tables after closing the DB $this->assertTrue(true); } else { diff --git a/tests/lib/DB/SchemaDiffTest.php b/tests/lib/DB/SchemaDiffTest.php new file mode 100644 index 0000000000000..b7bb3c2a9cb7b --- /dev/null +++ b/tests/lib/DB/SchemaDiffTest.php @@ -0,0 +1,99 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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 + * + */ + +namespace Test\DB; + +use Doctrine\DBAL\Schema\SchemaDiff; +use OC\DB\MDB2SchemaManager; +use OC\DB\MDB2SchemaReader; +use OCP\IConfig; +use Test\TestCase; + +/** + * Class MigratorTest + * + * @group DB + * + * @package Test\DB + */ +class SchemaDiffTest extends TestCase { + /** @var \Doctrine\DBAL\Connection $connection */ + private $connection; + + /** @var MDB2SchemaManager */ + private $manager; + + /** @var IConfig */ + private $config; + + /** @var string */ + private $testPrefix; + + protected function setUp() { + parent::setUp(); + + $this->config = \OC::$server->getConfig(); + $this->connection = \OC::$server->getDatabaseConnection(); + $this->manager = new MDB2SchemaManager($this->connection); + $this->testPrefix= strtolower($this->getUniqueID($this->config->getSystemValue('dbtableprefix', 'oc_'), 3)); + } + + protected function tearDown() { + $this->manager->removeDBStructure('static://test_db_scheme'); + parent::tearDown(); + } + + /** + * @dataProvider providesSchemaFiles + * @param string $xml + */ + public function testZeroChangeOnSchemaMigrations($xml) { + + $xml = str_replace( '*dbprefix*', $this->testPrefix, $xml ); + $schemaFile = 'static://test_db_scheme'; + file_put_contents($schemaFile, $xml); + + // apply schema + $this->manager->createDbFromStructure($schemaFile); + + $schemaReader = new MDB2SchemaReader($this->config, $this->connection->getDatabasePlatform()); + $endSchema = $schemaReader->loadSchemaFromFile($schemaFile); + + // get the diff + /** @var SchemaDiff $diff */ + $migrator = $this->manager->getMigrator(); + $diff = $this->invokePrivate($migrator, 'getDiff', [$endSchema, $this->connection]); + + // no sql statement is expected + $sqls = $diff->toSql($this->connection->getDatabasePlatform()); + $this->assertEquals([], $sqls); + } + + public function providesSchemaFiles() { + return [ + 'explicit test on autoincrement' => [file_get_contents(__DIR__ . '/schemDiffData/autoincrement.xml')], + 'explicit test on clob' => [file_get_contents(__DIR__ . '/schemDiffData/clob.xml')], + 'explicit test on unsigned' => [file_get_contents(__DIR__ . '/schemDiffData/unsigned.xml')], + 'explicit test on default -1' => [file_get_contents(__DIR__ . '/schemDiffData/default-1.xml')], + 'testing core schema' => [file_get_contents(__DIR__ . '/schemDiffData/core.xml')], + ]; + } +} diff --git a/tests/lib/DB/schemDiffData/autoincrement.xml b/tests/lib/DB/schemDiffData/autoincrement.xml new file mode 100644 index 0000000000000..458c5d8166f25 --- /dev/null +++ b/tests/lib/DB/schemDiffData/autoincrement.xml @@ -0,0 +1,16 @@ + + + + *dbprefix*external_config + + + config_id + integer + 0 + true + 1 + 6 + + +
+
diff --git a/tests/lib/DB/schemDiffData/clob.xml b/tests/lib/DB/schemDiffData/clob.xml new file mode 100644 index 0000000000000..08aef18c31d9b --- /dev/null +++ b/tests/lib/DB/schemDiffData/clob.xml @@ -0,0 +1,14 @@ + + + + *dbprefix*external_config + + + value + text + true + 100000 + + +
+
diff --git a/tests/lib/DB/schemDiffData/core.xml b/tests/lib/DB/schemDiffData/core.xml new file mode 100644 index 0000000000000..3775eb6cb37cd --- /dev/null +++ b/tests/lib/DB/schemDiffData/core.xml @@ -0,0 +1,1347 @@ + + + + + + + *dbprefix*appconfig + + + + + appid + text + + true + 32 + + + + configkey + text + + true + 64 + + + + configvalue + clob + false + + + +
+ + + + + *dbprefix*storages + + + + + id + text + + false + 64 + + + + numeric_id + integer + 0 + true + 1 + 4 + + + + available + integer + 1 + true + + + + last_checked + integer + + + +
+ + + + + *dbprefix*mounts + + + + + id + integer + 0 + true + 1 + 4 + + + + storage_id + integer + true + + + + + root_id + integer + true + + + + user_id + text + true + 64 + + + + mount_point + text + true + 4000 + + + + + +
+ + + + + *dbprefix*mimetypes + + + + + id + integer + 0 + true + 1 + 4 + + + + mimetype + text + + true + 255 + + + + +
+ + + + + *dbprefix*filecache + + + + + fileid + integer + 0 + true + 1 + 4 + + + + + storage + integer + + true + 4 + + + + path + text + + false + 4000 + + + + path_hash + text + + true + 32 + + + + + parent + integer + + true + 4 + + + + name + text + + false + 250 + + + + + mimetype + integer + + true + 4 + + + + + mimepart + integer + + true + 4 + + + + size + integer + + true + 8 + + + + mtime + integer + + true + 4 + + + + storage_mtime + integer + + true + 4 + + + + encrypted + integer + 0 + true + 4 + + + + unencrypted_size + integer + 0 + true + 8 + + + + etag + text + + false + 40 + + + + permissions + integer + 0 + false + 4 + + + + checksum + text + + false + 255 + + + + + + +
+ + + + + *dbprefix*group_user + + + + + + gid + text + + true + 64 + + + + + uid + text + + true + 64 + + + + +
+ + + + + *dbprefix*group_admin + + + + + + gid + text + + true + 64 + + + + + uid + text + + true + 64 + + + + +
+ + + + + *dbprefix*groups + + + + + gid + text + + true + 64 + + + + +
+ + + + + *dbprefix*preferences + + + + + + userid + text + + true + 64 + + + + appid + text + + true + 32 + + + + configkey + text + + true + 64 + + + + configvalue + clob + false + + + + +
+ + + + + *dbprefix*properties + + + + + id + 1 + integer + 0 + true + 4 + + + + + userid + text + + true + 64 + + + + propertypath + text + + true + 255 + + + + propertyname + text + + true + 255 + + + + propertyvalue + text + true + 255 + + + + +
+ + + + + *dbprefix*share + + + + + id + 1 + integer + 0 + true + 4 + + + + + share_type + integer + 0 + true + 1 + + + + + share_with + text + + false + 255 + + + + + + uid_owner + text + + true + 64 + + + + + + uid_initiator + text + + false + 64 + + + + + + + parent + integer + false + 4 + + + + + item_type + text + + true + 64 + + + + + item_source + text + + false + 255 + + + + item_target + text + + false + 255 + + + + + file_source + integer + false + 4 + + + + file_target + text + + false + 512 + + + + + permissions + integer + 0 + true + 1 + + + + + stime + integer + 0 + true + 8 + + + + + accepted + integer + 0 + true + 1 + + + + + expiration + timestamp + + false + + + + token + text + + false + 32 + + + + mail_send + integer + 0 + true + 1 + + + + +
+ + + + + *dbprefix*jobs + + + + + id + integer + 0 + true + 1 + true + 4 + + + + class + text + + true + 255 + + + + argument + text + + true + 4000 + + + + + last_run + integer + + false + + + + + last_checked + integer + + false + + + + + reserved_at + integer + + false + + + + +
+ + + + + *dbprefix*users + + + + + uid + text + + true + 64 + + + + displayname + text + + 64 + + + + password + text + + true + 255 + + + + + +
+ + + *dbprefix*authtoken + + + + + id + integer + 0 + true + 1 + true + 4 + + + + + uid + text + + true + 64 + + + + login_name + text + + true + 64 + + + + password + clob + + false + + + + name + clob + + true + + + + token + text + + true + 200 + + + + type + integer + 0 + true + true + 2 + + + + last_activity + integer + 0 + true + true + 4 + + + +
+ + + + + *dbprefix*vcategory + + + + + id + integer + 0 + true + 1 + true + 4 + + + + + uid + text + + true + 64 + + + + type + text + + true + 64 + + + + category + text + + true + 255 + + + +
+ + + + + *dbprefix*vcategory_to_object + + + + + objid + integer + 0 + true + true + 4 + + + + + categoryid + integer + 0 + true + true + 4 + + + + type + text + + true + 64 + + + + +
+ + + + *dbprefix*systemtag + + + + + id + integer + 0 + true + 1 + true + 4 + + + + + name + text + + true + 64 + + + + + visibility + integer + 1 + true + 1 + + + + + editable + integer + 1 + true + 1 + + + +
+ + + + + *dbprefix*systemtag_object_mapping + + + + + + objectid + text + + true + 64 + + + + + objecttype + text + + true + 64 + + + + + systemtagid + integer + 0 + true + true + 4 + + + + + +
+ + + + + *dbprefix*systemtag_group + + + + + + systemtagid + integer + 0 + true + true + 4 + + + + gid + string + true + + + + +
+ + + + + *dbprefix*privatedata + + + + + keyid + integer + 0 + true + true + 4 + 1 + + + + + user + text + + true + 64 + + + + app + text + + true + 255 + + + + key + text + + true + 255 + + + + value + text + + true + 255 + + + + +
+ + + + + *dbprefix*file_locks + + + + + id + integer + 0 + true + true + 4 + 1 + + + + lock + integer + 0 + true + 4 + + + + key + text + true + 64 + + + + ttl + integer + -1 + true + 4 + + + + +
+ + + + *dbprefix*comments + + + + + id + integer + 0 + true + true + 4 + 1 + + + + parent_id + integer + 0 + true + true + 4 + + + + topmost_parent_id + integer + 0 + true + true + 4 + + + + children_count + integer + 0 + true + true + 4 + + + + actor_type + text + + true + 64 + + + + actor_id + text + + true + 64 + + + + message + clob + + false + + + + verb + text + + false + 64 + + + + creation_timestamp + timestamp + + false + + + + latest_child_timestamp + timestamp + + false + + + + object_type + text + + true + 64 + + + + object_id + text + + true + 64 + + + + +
+ + + + *dbprefix*comments_read_markers + + + + + user_id + text + + true + 64 + + + + marker_datetime + timestamp + + false + + + + object_type + text + + true + 64 + + + + object_id + text + + true + 64 + + + + +
+ + + + *dbprefix*credentials + + + + + user + text + + false + 64 + + + + identifier + text + true + 64 + + + + credentials + clob + false + + + + +
+ +
diff --git a/tests/lib/DB/schemDiffData/default-1.xml b/tests/lib/DB/schemDiffData/default-1.xml new file mode 100644 index 0000000000000..39b95a1f27366 --- /dev/null +++ b/tests/lib/DB/schemDiffData/default-1.xml @@ -0,0 +1,51 @@ + + + + + + + *dbprefix*file_locks + + + + + id + integer + 0 + true + true + 4 + 1 + + + + lock + integer + 0 + true + 4 + + + + key + text + true + (stupid text) + 64 + + + + ttl + integer + -1 + true + 4 + + + + +
+ +
diff --git a/tests/lib/DB/schemDiffData/unsigned.xml b/tests/lib/DB/schemDiffData/unsigned.xml new file mode 100644 index 0000000000000..e89fd6a5d4ea9 --- /dev/null +++ b/tests/lib/DB/schemDiffData/unsigned.xml @@ -0,0 +1,68 @@ + + + + + + + *dbprefix*jobs + + + + + id + integer + 0 + true + 1 + true + 4 + + + + class + text + + true + 255 + + + + argument + text + + true + 4000 + + + + + last_run + integer + + false + + + + + last_checked + integer + + false + + + + + reserved_at + integer + + false + + + + +
+ +
From 0ccc412fccd56a20d833570ae206e8d7c417213b Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Wed, 29 Jun 2016 15:09:40 +0200 Subject: [PATCH 45/81] 9.1.0 RC 1 --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index b439ffbbdad85..93116539ffce9 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(9, 1, 0, 10); +$OC_Version = array(9, 1, 0, 11); // The human readable string -$OC_VersionString = '9.1.0 beta 2'; +$OC_VersionString = '9.1.0 RC 1'; $OC_VersionCanBeUpgradedFrom = array(9, 0); From 4c426ad9707651820dbeb0c7d0c798fcff1d690b Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Wed, 29 Jun 2016 15:11:48 +0200 Subject: [PATCH 46/81] fix version string --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index 93116539ffce9..86fb9bbf54cb4 100644 --- a/version.php +++ b/version.php @@ -28,7 +28,7 @@ $OC_Version = array(9, 1, 0, 11); // The human readable string -$OC_VersionString = '9.1.0 RC 1'; +$OC_VersionString = '9.1.0 RC1'; $OC_VersionCanBeUpgradedFrom = array(9, 0); From 79ab46b28630bc57117c3214d76a6aab116e5092 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 29 Jun 2016 15:53:23 +0200 Subject: [PATCH 47/81] mysql only works with 3 byte UTF-8 --- .drone.yml | 2 +- tests/lib/Files/Cache/CacheTest.php | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index df58c126a058c..fc86e72c2b9e0 100644 --- a/.drone.yml +++ b/.drone.yml @@ -20,7 +20,7 @@ build: mysql: image: morrisjobke/nextcloud-ci-php7:1.0.4 commands: - - sleep 10 # gives the database enough time to initialize + - sleep 15 # gives the database enough time to initialize - rm -rf data/* config/config.php # TODO: remove this - temporary fix for CI issues - git submodule update --init - ./autotest.sh mysql diff --git a/tests/lib/Files/Cache/CacheTest.php b/tests/lib/Files/Cache/CacheTest.php index 615bb32f62c6e..bfc3c1be7b862 100644 --- a/tests/lib/Files/Cache/CacheTest.php +++ b/tests/lib/Files/Cache/CacheTest.php @@ -9,6 +9,8 @@ namespace Test\Files\Cache; +use Doctrine\DBAL\Platforms\MySqlPlatform; + class LongId extends \OC\Files\Storage\Temporary { public function getId() { return 'long:' . str_repeat('foo', 50) . parent::getId(); @@ -108,6 +110,12 @@ public function testPartial() { * @dataProvider folderDataProvider */ public function testFolder($folder) { + if(strpos($folder, 'F09F9890')) { + // 4 byte UTF doesn't work on mysql + if(\OC::$server->getDatabaseConnection()->getDatabasePlatform() instanceof MySqlPlatform) { + $this->markTestSkipped('MySQL doesn\'t support 4 byte UTF-8'); + } + } $file2 = $folder.'/bar'; $file3 = $folder.'/foo'; $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); From 7adfe950ae830e5b3a8f50f8a28894b95c96178c Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 29 Jun 2016 12:08:26 +0200 Subject: [PATCH 48/81] Fix update notification text * thanks to ungesundes_halbwissen @ transifex --- apps/updatenotification/templates/admin.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/updatenotification/templates/admin.php b/apps/updatenotification/templates/admin.php index 0be070cac30be..b1cc76534e357 100644 --- a/apps/updatenotification/templates/admin.php +++ b/apps/updatenotification/templates/admin.php @@ -47,7 +47,9 @@
- t('Only notification for app updates are available, because the selected update channel for the server itself does not allow notifications.')); ?> + t('Only notification for app updates are available.')); ?> + t('The selected update channel makes dedicated notifications for the server obsolete.')); ?> + t('The selected update channel does not support updates of the server.')); ?>

From e67615ef0cfba880d1c0ed151f57d78e0fe92dd3 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Thu, 30 Jun 2016 01:55:56 -0400 Subject: [PATCH 49/81] [tx-robot] updated from transifex --- apps/comments/l10n/pt_PT.js | 3 +++ apps/comments/l10n/pt_PT.json | 3 +++ apps/user_ldap/l10n/he.js | 6 ++++++ apps/user_ldap/l10n/he.json | 6 ++++++ core/l10n/lb.js | 7 ++++++- core/l10n/lb.json | 7 ++++++- settings/l10n/pt_BR.js | 1 + settings/l10n/pt_BR.json | 1 + 8 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apps/comments/l10n/pt_PT.js b/apps/comments/l10n/pt_PT.js index a015d02ae6ba5..17632c2f04651 100644 --- a/apps/comments/l10n/pt_PT.js +++ b/apps/comments/l10n/pt_PT.js @@ -12,6 +12,9 @@ OC.L10N.register( "More comments..." : "Mais comentários...", "Save" : "Guardar", "Allowed characters {count} of {max}" : "{count} de {max} caracteres restantes", + "Error occurred while retrieving comment with id {id}" : "Ocorreu um erro ao tentar obter o comentário com o id {id}", + "Error occurred while updating comment with id {id}" : "Ocorreu um erro ao tentar atualizar o comentário com o id {id}", + "Error occurred while posting comment" : "Ocorreu um erro ao tentar publicar o comentário", "{count} unread comments" : "{count} comentários não lidos", "Comment" : "Comentário", "Comments for files (always listed in stream)" : "Comentários aos ficheiros (listados sempre na transmissão)", diff --git a/apps/comments/l10n/pt_PT.json b/apps/comments/l10n/pt_PT.json index 244892c4ac7f4..00f024034d2ac 100644 --- a/apps/comments/l10n/pt_PT.json +++ b/apps/comments/l10n/pt_PT.json @@ -10,6 +10,9 @@ "More comments..." : "Mais comentários...", "Save" : "Guardar", "Allowed characters {count} of {max}" : "{count} de {max} caracteres restantes", + "Error occurred while retrieving comment with id {id}" : "Ocorreu um erro ao tentar obter o comentário com o id {id}", + "Error occurred while updating comment with id {id}" : "Ocorreu um erro ao tentar atualizar o comentário com o id {id}", + "Error occurred while posting comment" : "Ocorreu um erro ao tentar publicar o comentário", "{count} unread comments" : "{count} comentários não lidos", "Comment" : "Comentário", "Comments for files (always listed in stream)" : "Comentários aos ficheiros (listados sempre na transmissão)", diff --git a/apps/user_ldap/l10n/he.js b/apps/user_ldap/l10n/he.js index 8ff1a2037e47f..f0eb5d3529787 100644 --- a/apps/user_ldap/l10n/he.js +++ b/apps/user_ldap/l10n/he.js @@ -97,6 +97,7 @@ OC.L10N.register( "Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge." : "נמנע מבקשות אוטומטיות של LDAP. מועדף עבור התקנות גדולות, אבל מחייב ידע מסויים של LDAP.", "Manually enter LDAP filters (recommended for large directories)" : "הכנסת מסנני LDAP ידנית (מומלץ עבוק תיקיות גדולות)", "%s access is limited to users meeting these criteria:" : "%s גישה מוגבלת למשתמשים שעונים על קריטריונים אלו:", + "The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "העצמים הבסיסיים למשתמשים הם organizationalPerson, person, user, וכן inetOrgPerson. אם אינך בטוח איזה עצם לבחור, יש להתייעף עם מנהל התיקייה.", "The filter specifies which LDAP users shall have access to the %s instance." : "הסינון קובע לאיזו משתמשי LDAP תהיה יכולת כניסה למקרה %s.", "Verify settings and count users" : "מאמת הגדרות וסופר משתמשים", "Saving" : "שמירה", @@ -123,17 +124,21 @@ OC.L10N.register( "User Display Name Field" : "שדה שם תצוגה למשתמש", "The LDAP attribute to use to generate the user's display name." : "תכונת LDAP לשימוש כדי להפיק את שם התצוגה של המשתמש.", "2nd User Display Name Field" : "שדה שני לשם תצוגת משתמש", + "Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«." : "אופציונאלי. מאפיין LDAP שיתווסף לפני השם בסוגריים. לדוגמא »John Doe (john.doe@example.org)«.", "Base User Tree" : "עץ משתמש בסיסי", "One User Base DN per line" : "משתמש DN בסיסי אחד לשורה", "User Search Attributes" : "מאפייני חיפוש משתמש", "Optional; one attribute per line" : "אופציונאלי; מאפיין אחד בשורה", "Group Display Name Field" : "שדה שם תצוגה לקבוצה", + "The LDAP attribute to use to generate the groups's display name." : "מאפיין LDAP לשימוש בהפקת שם תצוגת הקבוצה.", "Base Group Tree" : "עץ קבוצה בסיסי", "One Group Base DN per line" : "קבוצת DN בסיסית לשורה", "Group Search Attributes" : "מאפייני חיפוש קבוצה", "Group-Member association" : "שיוך חברי-קבוצה", "Dynamic Group Member URL" : "נתיב חבר קבוצה דינמית", + "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "מאפיין LDAP שבעצם קבוצה מכיל נתיב חיפוש שקובע אילו עצמים שייכים לקבוצה. (הגדרה ריקה מבטלת אפשרות לחברות בקבוצה דינמית.)", "Nested Groups" : "קבוצות משנה", + "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "כאשר מופעל, קיימת תמיכה לקבוצות המכילות קבוצות משנה. (עובד רק אם מאפיין חבר הקבוצה מכיל DN-ים.)", "Paging chunksize" : "Paging chunksize", "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Chunksize משמש לחיפושי paged LDAP שעלולים להחזיר תוצאות גסות כמו ספירת משתמש או קבוצה. (הגדרה כ- 0 מנטרל חיפושי paged LDAP במצבים אלה.)", "Special Attributes" : "מאפיינים מיוחדים", @@ -142,6 +147,7 @@ OC.L10N.register( "in bytes" : "בבתים", "Email Field" : "שדה דואר אלקטרוני", "User Home Folder Naming Rule" : "כלל קביעת שם תיקיית בית למשתמש", + "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." : "יש להשאיר ריק לשם משתמש (ברירת מחדל). לחילופין, יש להגדיר מאפיין LDAP/AD.", "Internal Username" : "שם משתמש פנימי", "Internal Username Attribute:" : "מאפיין שם משתמש פנימי:", "Override UUID detection" : "דריסת זיהוי UUID", diff --git a/apps/user_ldap/l10n/he.json b/apps/user_ldap/l10n/he.json index 0ad2d1fc61b15..75fa25130cc17 100644 --- a/apps/user_ldap/l10n/he.json +++ b/apps/user_ldap/l10n/he.json @@ -95,6 +95,7 @@ "Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge." : "נמנע מבקשות אוטומטיות של LDAP. מועדף עבור התקנות גדולות, אבל מחייב ידע מסויים של LDAP.", "Manually enter LDAP filters (recommended for large directories)" : "הכנסת מסנני LDAP ידנית (מומלץ עבוק תיקיות גדולות)", "%s access is limited to users meeting these criteria:" : "%s גישה מוגבלת למשתמשים שעונים על קריטריונים אלו:", + "The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "העצמים הבסיסיים למשתמשים הם organizationalPerson, person, user, וכן inetOrgPerson. אם אינך בטוח איזה עצם לבחור, יש להתייעף עם מנהל התיקייה.", "The filter specifies which LDAP users shall have access to the %s instance." : "הסינון קובע לאיזו משתמשי LDAP תהיה יכולת כניסה למקרה %s.", "Verify settings and count users" : "מאמת הגדרות וסופר משתמשים", "Saving" : "שמירה", @@ -121,17 +122,21 @@ "User Display Name Field" : "שדה שם תצוגה למשתמש", "The LDAP attribute to use to generate the user's display name." : "תכונת LDAP לשימוש כדי להפיק את שם התצוגה של המשתמש.", "2nd User Display Name Field" : "שדה שני לשם תצוגת משתמש", + "Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«." : "אופציונאלי. מאפיין LDAP שיתווסף לפני השם בסוגריים. לדוגמא »John Doe (john.doe@example.org)«.", "Base User Tree" : "עץ משתמש בסיסי", "One User Base DN per line" : "משתמש DN בסיסי אחד לשורה", "User Search Attributes" : "מאפייני חיפוש משתמש", "Optional; one attribute per line" : "אופציונאלי; מאפיין אחד בשורה", "Group Display Name Field" : "שדה שם תצוגה לקבוצה", + "The LDAP attribute to use to generate the groups's display name." : "מאפיין LDAP לשימוש בהפקת שם תצוגת הקבוצה.", "Base Group Tree" : "עץ קבוצה בסיסי", "One Group Base DN per line" : "קבוצת DN בסיסית לשורה", "Group Search Attributes" : "מאפייני חיפוש קבוצה", "Group-Member association" : "שיוך חברי-קבוצה", "Dynamic Group Member URL" : "נתיב חבר קבוצה דינמית", + "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "מאפיין LDAP שבעצם קבוצה מכיל נתיב חיפוש שקובע אילו עצמים שייכים לקבוצה. (הגדרה ריקה מבטלת אפשרות לחברות בקבוצה דינמית.)", "Nested Groups" : "קבוצות משנה", + "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "כאשר מופעל, קיימת תמיכה לקבוצות המכילות קבוצות משנה. (עובד רק אם מאפיין חבר הקבוצה מכיל DN-ים.)", "Paging chunksize" : "Paging chunksize", "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Chunksize משמש לחיפושי paged LDAP שעלולים להחזיר תוצאות גסות כמו ספירת משתמש או קבוצה. (הגדרה כ- 0 מנטרל חיפושי paged LDAP במצבים אלה.)", "Special Attributes" : "מאפיינים מיוחדים", @@ -140,6 +145,7 @@ "in bytes" : "בבתים", "Email Field" : "שדה דואר אלקטרוני", "User Home Folder Naming Rule" : "כלל קביעת שם תיקיית בית למשתמש", + "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." : "יש להשאיר ריק לשם משתמש (ברירת מחדל). לחילופין, יש להגדיר מאפיין LDAP/AD.", "Internal Username" : "שם משתמש פנימי", "Internal Username Attribute:" : "מאפיין שם משתמש פנימי:", "Override UUID detection" : "דריסת זיהוי UUID", diff --git a/core/l10n/lb.js b/core/l10n/lb.js index c6865a9144111..5238ada0b3a02 100644 --- a/core/l10n/lb.js +++ b/core/l10n/lb.js @@ -264,6 +264,11 @@ OC.L10N.register( "These apps will be updated:" : "D!es Apps wäerten aktualiséiert ginn:", "These incompatible apps will be disabled:" : "Dës inkompatibel Apps wäerten ofgeschalt ginn:", "The theme %s has been disabled." : "D'Thema %s gouf ofgeschalt.", - "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "W.e.g. géi sécher dass d'Datebank, de configuréierten Dossier an den Daten Dossier ofgeséchert sinn éiers de weider gees." + "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "W.e.g. géi sécher dass d'Datebank, de configuréierten Dossier an den Daten Dossier ofgeséchert sinn éiers de weider gees.", + "Start update" : "Update starten", + "Detailed logs" : "Detailléiert Loggs", + "For help, see the documentation." : "Fir Hëllef, kuck am Documentatioun.", + "This %s instance is currently in maintenance mode, which may take a while." : "Dës %s Instanz ass am Moment am Maintenance Modus, dat kënnt ee Moment brauche.", + "This page will refresh itself when the %s instance is available again." : "Dës Säit luet nees automatesch wann d' %s Instanz nees disponibel ass." }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/lb.json b/core/l10n/lb.json index f3af3f00ee6d2..534b50f9e9672 100644 --- a/core/l10n/lb.json +++ b/core/l10n/lb.json @@ -262,6 +262,11 @@ "These apps will be updated:" : "D!es Apps wäerten aktualiséiert ginn:", "These incompatible apps will be disabled:" : "Dës inkompatibel Apps wäerten ofgeschalt ginn:", "The theme %s has been disabled." : "D'Thema %s gouf ofgeschalt.", - "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "W.e.g. géi sécher dass d'Datebank, de configuréierten Dossier an den Daten Dossier ofgeséchert sinn éiers de weider gees." + "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "W.e.g. géi sécher dass d'Datebank, de configuréierten Dossier an den Daten Dossier ofgeséchert sinn éiers de weider gees.", + "Start update" : "Update starten", + "Detailed logs" : "Detailléiert Loggs", + "For help, see the documentation." : "Fir Hëllef, kuck am Documentatioun.", + "This %s instance is currently in maintenance mode, which may take a while." : "Dës %s Instanz ass am Moment am Maintenance Modus, dat kënnt ee Moment brauche.", + "This page will refresh itself when the %s instance is available again." : "Dës Säit luet nees automatesch wann d' %s Instanz nees disponibel ass." },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/settings/l10n/pt_BR.js b/settings/l10n/pt_BR.js index 3f4cbff71adbc..a9d9427a782e6 100644 --- a/settings/l10n/pt_BR.js +++ b/settings/l10n/pt_BR.js @@ -279,6 +279,7 @@ OC.L10N.register( "An app password is a passcode that gives an app or device permissions to access your %s account." : "A senha do aplicativo é um código de acesso que dá ao aplicativo ou dispositivo permissões para acessar sua conta %s.", "App name" : "Nome do aplicativo", "Create new app password" : "Criar uma nova senha do aplicativo", + "Use the credentials below to configure your app or device." : "Use as credenciais abaixo para configurar seu aplicativo ou dispositivo.", "Username" : "Nome de Usuário", "Done" : "Concluída", "Get the apps to sync your files" : "Obtenha apps para sincronizar seus arquivos", diff --git a/settings/l10n/pt_BR.json b/settings/l10n/pt_BR.json index 249a3e29c076c..1ed78c7925e1e 100644 --- a/settings/l10n/pt_BR.json +++ b/settings/l10n/pt_BR.json @@ -277,6 +277,7 @@ "An app password is a passcode that gives an app or device permissions to access your %s account." : "A senha do aplicativo é um código de acesso que dá ao aplicativo ou dispositivo permissões para acessar sua conta %s.", "App name" : "Nome do aplicativo", "Create new app password" : "Criar uma nova senha do aplicativo", + "Use the credentials below to configure your app or device." : "Use as credenciais abaixo para configurar seu aplicativo ou dispositivo.", "Username" : "Nome de Usuário", "Done" : "Concluída", "Get the apps to sync your files" : "Obtenha apps para sincronizar seus arquivos", From dc3555409141ee0667e639fd26ace8844c225489 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 30 Jun 2016 11:10:48 +0200 Subject: [PATCH 50/81] Prevent infinite loop in search auto-nextpage When loading the next page of search results, make sure that the loop can end if there are no more elements in case the total doesn't match. Also added a check to avoid recomputing the search results whenever the setFilter() is called with the same value. This happens when navigating away to another folder, the search field gets cleared automatically and it calls FileList.setFilter(''). --- apps/files/js/filelist.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 18f17a7207c27..690e5e70fdb7c 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -2352,13 +2352,16 @@ */ setFilter:function(filter) { var total = 0; + if (this._filter === filter) { + return; + } this._filter = filter; this.fileSummary.setFilter(filter, this.files); total = this.fileSummary.getTotal(); if (!this.$el.find('.mask').exists()) { this.hideIrrelevantUIWhenNoFilesMatch(); } - var that = this; + var visibleCount = 0; filter = filter.toLowerCase(); @@ -2378,7 +2381,7 @@ if (visibleCount < total) { $trs = this._nextPage(false); } - } while (visibleCount < total); + } while (visibleCount < total && $trs.length > 0); this.$container.trigger('scroll'); }, From 93c8458ab39e78f2df2b759ed9201f0b337044bc Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 30 Jun 2016 11:09:20 +0200 Subject: [PATCH 51/81] add some additonal permission checks to the webdav backend --- apps/dav/lib/Connector/Sabre/ObjectTree.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/Connector/Sabre/ObjectTree.php b/apps/dav/lib/Connector/Sabre/ObjectTree.php index 9e7d876187da4..07052e30301a4 100644 --- a/apps/dav/lib/Connector/Sabre/ObjectTree.php +++ b/apps/dav/lib/Connector/Sabre/ObjectTree.php @@ -71,7 +71,7 @@ public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\File * is present. * * @param string $path chunk file path to convert - * + * * @return string path to real file */ private function resolveChunkFile($path) { @@ -196,6 +196,15 @@ public function move($sourcePath, $destinationPath) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } + $infoDestination = $this->fileView->getFileInfo(dirname($destinationPath)); + $infoSource = $this->fileView->getFileInfo($sourcePath); + $destinationPermission = $infoDestination && $infoDestination->isUpdateable(); + $sourcePermission = $infoSource && $infoSource->isDeletable(); + + if (!$destinationPermission || !$sourcePermission) { + throw new Forbidden(); + } + $targetNodeExists = $this->nodeExists($destinationPath); $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) { @@ -273,6 +282,12 @@ public function copy($source, $destination) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } + + $info = $this->fileView->getFileInfo(dirname($destination)); + if ($info && !$info->isUpdateable()) { + throw new Forbidden(); + } + // this will trigger existence check $this->getNodeForPath($source); From 7e7a15f880e11f7b1846391d718d696e44220e5c Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 30 Jun 2016 10:29:32 +0200 Subject: [PATCH 52/81] check permissions before rollback --- apps/files_versions/lib/Storage.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index 93f8b848ce8c5..b14210af7b1ce 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -77,7 +77,7 @@ class Storage { //until the end one version per week 6 => array('intervalEndsAfter' => -1, 'step' => 604800), ); - + /** @var \OCA\Files_Versions\AppInfo\Application */ private static $application; @@ -324,6 +324,13 @@ public static function rollback($file, $revision) { $files_view = new View('/'. User::getUser().'/files'); $versionCreated = false; + $fileInfo = $files_view->getFileInfo($file); + + // check if user has the permissions to revert a version + if (!$fileInfo->isUpdateable()) { + return false; + } + //first create a new version $version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename); if (!$users_view->file_exists($version)) { @@ -337,10 +344,9 @@ public static function rollback($file, $revision) { // This has to happen manually here since the file is manually copied below $oldVersion = $users_view->getFileInfo($fileToRestore)->getEncryptedVersion(); $oldFileInfo = $users_view->getFileInfo($fileToRestore); - $newFileInfo = $files_view->getFileInfo($filename); - $cache = $newFileInfo->getStorage()->getCache(); + $cache = $fileInfo->getStorage()->getCache(); $cache->update( - $newFileInfo->getId(), [ + $fileInfo->getId(), [ 'encrypted' => $oldVersion, 'encryptedVersion' => $oldVersion, 'size' => $oldFileInfo->getSize() @@ -680,7 +686,7 @@ private static function scheduleExpire($uid, $fileName) { public static function expire($filename) { $config = \OC::$server->getConfig(); $expiration = self::getExpiration(); - + if($config->getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' && $expiration->isEnabled()) { if (!Filesystem::file_exists($filename)) { From 4e215437afcd9daf815dedb8a435d67be5693596 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Thu, 30 Jun 2016 12:15:58 +0200 Subject: [PATCH 53/81] Add integration tests --- .../integration/features/bootstrap/WebDav.php | 18 ++++++++++++ .../features/webdav-related.feature | 29 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/build/integration/features/bootstrap/WebDav.php b/build/integration/features/bootstrap/WebDav.php index 0abb8667739b0..23f80c2fa766c 100644 --- a/build/integration/features/bootstrap/WebDav.php +++ b/build/integration/features/bootstrap/WebDav.php @@ -42,6 +42,7 @@ public function makeDavRequest($user, $method, $path, $headers, $body = null){ $request->setBody($body); } + return $client->send($request); } @@ -70,6 +71,23 @@ public function userMovesFile($user, $fileSource, $fileDestination){ $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); } + /** + * @When /^User "([^"]*)" copies file "([^"]*)" to "([^"]*)"$/ + * @param string $user + * @param string $fileSource + * @param string $fileDestination + */ + public function userCopiesFileTo($user, $fileSource, $fileDestination) { + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath; + $headers['Destination'] = $fullUrl . $fileDestination; + try { + $this->response = $this->makeDavRequest($user, 'COPY', $fileSource, $headers); + } catch (\GuzzleHttp\Exception\ClientException $e) { + // 4xx and 5xx responses cause an exception + $this->response = $e->getResponse(); + } + } + /** * @When /^Downloading file "([^"]*)" with range "([^"]*)"$/ * @param string $fileSource diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index 06df280ea6468..a135f077f7113 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -257,3 +257,32 @@ Feature: webdav-related When Downloading file "/welcome.txt" as "userToBeDisabled" Then the HTTP status code should be "503" + Scenario: Copying files into a folder with edit permissions + Given using dav path "remote.php/webdav" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testcopypermissionsAllowed" + And as "user1" creating a share with + | path | testcopypermissionsAllowed | + | shareType | 0 | + | permissions | 31 | + | shareWith | user0 | + And User "user0" uploads file with content "copytest" to "/copytest.txt" + When User "user0" copies file "/copytest.txt" to "/testcopypermissionsAllowed/copytest.txt" + Then the HTTP status code should be "201" + + Scenario: Copying files into a folder without edit permissions + Given using dav path "remote.php/webdav" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testcopypermissionsNotAllowed" + And as "user1" creating a share with + | path | testcopypermissionsNotAllowed | + | shareType | 0 | + | permissions | 1 | + | shareWith | user0 | + And User "user0" uploads file with content "copytest" to "/copytest.txt" + When User "user0" copies file "/copytest.txt" to "/testcopypermissionsNotAllowed/copytest.txt" + Then the HTTP status code should be "403" From 26aba88f2584d5007be17ee48b24cd246da7ab36 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Thu, 30 Jun 2016 12:43:58 +0200 Subject: [PATCH 54/81] Set content-type to "application/octet-stream" Some browsers such as Firefox on Microsoft Windows otherwise do offer to open the file directly which is kinda silly. --- settings/Controller/LogSettingsController.php | 3 ++- tests/Settings/Controller/LogSettingsControllerTest.php | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/settings/Controller/LogSettingsController.php b/settings/Controller/LogSettingsController.php index 4863c2369be26..6c9fe76c2473d 100644 --- a/settings/Controller/LogSettingsController.php +++ b/settings/Controller/LogSettingsController.php @@ -105,7 +105,8 @@ public function getEntries($count=50, $offset=0) { */ public function download() { $resp = new StreamResponse(\OC\Log\Owncloud::getLogFilePath()); - $resp->addHeader('Content-Disposition', 'attachment; filename="owncloud.log"'); + $resp->addHeader('Content-Type', 'application/octet-stream'); + $resp->addHeader('Content-Disposition', 'attachment; filename="nextcloud.log"'); return $resp; } } diff --git a/tests/Settings/Controller/LogSettingsControllerTest.php b/tests/Settings/Controller/LogSettingsControllerTest.php index 092c04aecc7aa..e3cfa072d08c1 100644 --- a/tests/Settings/Controller/LogSettingsControllerTest.php +++ b/tests/Settings/Controller/LogSettingsControllerTest.php @@ -12,6 +12,7 @@ use \OC\Settings\Application; use OC\Settings\Controller\LogSettingsController; +use OCP\AppFramework\Http\StreamResponse; /** * @package Tests\Settings\Controller @@ -70,6 +71,9 @@ public function logLevelData() { public function testDownload() { $response = $this->logSettingsController->download(); - $this->assertInstanceOf('\OCP\AppFramework\Http\StreamResponse', $response); + $expected = new StreamResponse(\OC\Log\Owncloud::getLogFilePath()); + $expected->addHeader('Content-Type', 'application/octet-stream'); + $expected->addHeader('Content-Disposition', 'attachment; filename="nextcloud.log"'); + $this->assertEquals($expected, $response); } } From 54ab972f0e45d0c192a705d794f9f4db7397b6e8 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Thu, 30 Jun 2016 13:17:53 +0200 Subject: [PATCH 55/81] Add required $message parameter --- apps/dav/lib/Connector/Sabre/ObjectTree.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/Connector/Sabre/ObjectTree.php b/apps/dav/lib/Connector/Sabre/ObjectTree.php index 07052e30301a4..100e5ec56a2bb 100644 --- a/apps/dav/lib/Connector/Sabre/ObjectTree.php +++ b/apps/dav/lib/Connector/Sabre/ObjectTree.php @@ -202,7 +202,7 @@ public function move($sourcePath, $destinationPath) { $sourcePermission = $infoSource && $infoSource->isDeletable(); if (!$destinationPermission || !$sourcePermission) { - throw new Forbidden(); + throw new Forbidden('No permissions to move object.'); } $targetNodeExists = $this->nodeExists($destinationPath); @@ -285,7 +285,7 @@ public function copy($source, $destination) { $info = $this->fileView->getFileInfo(dirname($destination)); if ($info && !$info->isUpdateable()) { - throw new Forbidden(); + throw new Forbidden('No permissions to move object.'); } // this will trigger existence check From 62cc9f913131fb8f9daab9e69a9d9de5d7d9815c Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Thu, 30 Jun 2016 13:19:50 +0200 Subject: [PATCH 56/81] Add proper throws PHP docs --- apps/dav/lib/Connector/Sabre/ObjectTree.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/Connector/Sabre/ObjectTree.php b/apps/dav/lib/Connector/Sabre/ObjectTree.php index 100e5ec56a2bb..8f5f7be2505a9 100644 --- a/apps/dav/lib/Connector/Sabre/ObjectTree.php +++ b/apps/dav/lib/Connector/Sabre/ObjectTree.php @@ -186,9 +186,13 @@ public function getNodeForPath($path) { * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node - * @throws \Sabre\DAV\Exception\BadRequest - * @throws \Sabre\DAV\Exception\ServiceUnavailable + * @throws FileLocked + * @throws Forbidden + * @throws InvalidPath * @throws \Sabre\DAV\Exception\Forbidden + * @throws \Sabre\DAV\Exception\Locked + * @throws \Sabre\DAV\Exception\NotFound + * @throws \Sabre\DAV\Exception\ServiceUnavailable * @return int */ public function move($sourcePath, $destinationPath) { @@ -274,6 +278,13 @@ public function move($sourcePath, $destinationPath) { * * @param string $source * @param string $destination + * @throws FileLocked + * @throws Forbidden + * @throws InvalidPath + * @throws \Exception + * @throws \Sabre\DAV\Exception\Forbidden + * @throws \Sabre\DAV\Exception\Locked + * @throws \Sabre\DAV\Exception\NotFound * @throws \Sabre\DAV\Exception\ServiceUnavailable * @return void */ From ea18d86566939229604825ab1b147643db67f55e Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Thu, 30 Jun 2016 13:46:08 +0200 Subject: [PATCH 57/81] Fix tests --- .../unit/Connector/Sabre/ObjectTreeTest.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php index 4a5e43376c0fc..96d4357660e51 100644 --- a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php @@ -35,6 +35,7 @@ public function __construct($updatables, $deletables, $canRename = true) { $this->updatables = $updatables; $this->deletables = $deletables; $this->canRename = $canRename; + $this->lockingProvider = \OC::$server->getLockingProvider(); } public function isUpdatable($path) { @@ -56,6 +57,11 @@ public function rename($path1, $path2) { public function getRelativePath($path) { return $path; } + + public function getFileInfo($path, $includeMountPoints = true) { + $objectTreeTest = new ObjectTreeTest(); + return $objectTreeTest->getFileInfoMock(); + } } /** @@ -67,6 +73,20 @@ public function getRelativePath($path) { */ class ObjectTreeTest extends \Test\TestCase { + public function getFileInfoMock() { + $mock = $this->getMock('\OCP\Files\FileInfo'); + $mock + ->expects($this->any()) + ->method('isDeletable') + ->willReturn(true); + $mock + ->expects($this->any()) + ->method('isUpdateable') + ->willReturn(true); + + return $mock; + } + /** * @dataProvider moveFailedProvider * @expectedException \Sabre\DAV\Exception\Forbidden From 726052b351f6af12e4ebc566b688327006e42afb Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 30 Jun 2016 13:50:31 +0200 Subject: [PATCH 58/81] fix error message --- apps/dav/lib/Connector/Sabre/ObjectTree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dav/lib/Connector/Sabre/ObjectTree.php b/apps/dav/lib/Connector/Sabre/ObjectTree.php index 8f5f7be2505a9..d8c1d71e7f173 100644 --- a/apps/dav/lib/Connector/Sabre/ObjectTree.php +++ b/apps/dav/lib/Connector/Sabre/ObjectTree.php @@ -296,7 +296,7 @@ public function copy($source, $destination) { $info = $this->fileView->getFileInfo(dirname($destination)); if ($info && !$info->isUpdateable()) { - throw new Forbidden('No permissions to move object.'); + throw new Forbidden('No permissions to copy object.'); } // this will trigger existence check From 74b29a0ffa908e75473a8b511b5f6dba2809e756 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Fri, 1 Jul 2016 01:57:04 -0400 Subject: [PATCH 59/81] [tx-robot] updated from transifex --- apps/comments/l10n/nl.js | 1 + apps/comments/l10n/nl.json | 1 + core/l10n/ast.js | 40 ++++++++++++++++++++++++++++++++++++++ core/l10n/ast.json | 40 ++++++++++++++++++++++++++++++++++++++ core/l10n/da.js | 21 ++++++++++++++++++++ core/l10n/da.json | 21 ++++++++++++++++++++ settings/l10n/nl.js | 1 + settings/l10n/nl.json | 1 + 8 files changed, 126 insertions(+) diff --git a/apps/comments/l10n/nl.js b/apps/comments/l10n/nl.js index 4ccce751303bf..5643468947137 100644 --- a/apps/comments/l10n/nl.js +++ b/apps/comments/l10n/nl.js @@ -14,6 +14,7 @@ OC.L10N.register( "Allowed characters {count} of {max}" : "{count} van de {max} toegestane tekens", "Error occurred while retrieving comment with id {id}" : "Er trad een fout op bij het ophalen van reactie met id {id}", "Error occurred while updating comment with id {id}" : "Er trad een fout op bij het bijwerken van reactie met id {id}", + "Error occurred while posting comment" : "Er trad een fout op bij het plaatsten van een reactie", "{count} unread comments" : "{count} ongelezen reacties", "Comment" : "Reactie", "Comments for files (always listed in stream)" : "Reacties voor bestanden (altijd getoond in de stroom)", diff --git a/apps/comments/l10n/nl.json b/apps/comments/l10n/nl.json index be26788962cbe..d8de61d10cbf8 100644 --- a/apps/comments/l10n/nl.json +++ b/apps/comments/l10n/nl.json @@ -12,6 +12,7 @@ "Allowed characters {count} of {max}" : "{count} van de {max} toegestane tekens", "Error occurred while retrieving comment with id {id}" : "Er trad een fout op bij het ophalen van reactie met id {id}", "Error occurred while updating comment with id {id}" : "Er trad een fout op bij het bijwerken van reactie met id {id}", + "Error occurred while posting comment" : "Er trad een fout op bij het plaatsten van een reactie", "{count} unread comments" : "{count} ongelezen reacties", "Comment" : "Reactie", "Comments for files (always listed in stream)" : "Reacties voor bestanden (altijd getoond in de stroom)", diff --git a/core/l10n/ast.js b/core/l10n/ast.js index ffb8fa94e2db4..c538630150bb8 100644 --- a/core/l10n/ast.js +++ b/core/l10n/ast.js @@ -131,6 +131,18 @@ OC.L10N.register( "Strong password" : "Contraseña mui bona", "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "El to sirvidor web entá nun ta configuráu afayadizamente pa permitir la sincronización de ficheros porque la interfaz WebDAV paez tar rota.", "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our documentation." : "El to sirvidor web nun ta configuráu correchamente pa resolver \"{url}\". Pues atopar más información en nuesa documentación .", + "This server has no working Internet connection. 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. We suggest to enable Internet connection for this server if you want to have all features." : "Esti sirvidor nun tien conexón a Internet. Esto significa que dalgunes de les carauterístiques nun van funcionar, como'l montaxe d'almacenamiento esternu, les notificaciones sobre anovamientos, la instalación d'aplicaciones de terceros, l'accesu a los ficheros de mou remotu o l'unviu de correos-e de notificación. Suxerimos habilitar una conexón a Internet nesti sirvidor pa esfrutar de toles funciones.", + "No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our documentation." : "Configuróse ensin la memoria caché. P'ameyorar el so rendimientu configure un Memcache si ta disponible. Puede atopar más información na nuesa documentación.", + "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our documentation." : "/dev/urandom nun ye llexible por PHP que amás nun ye recomendable por razones de seguridá. Pues atopar más información na nuesa documentación.", + "You are currently running PHP {version}. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by the PHP Group as soon as your distribution supports it." : "Ta executándose anguaño la {version} PHP. Convidamoste a actualizar la to versión PHP p'aprovechate del rendimientu y actualizaciones de seguridá proporcionaes pol Grupu PHP desque la so distribución sofitelo.", + "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our documentation." : "La configuración de les cabeceres de proxy inverses ye incorrecta , o tas aportando ownCloud dende un proxy d'enfotu . Si nun tas aportando a ownCloud dende un proxy d'enfotu, esto ye un problema de seguridá y puede dexar a un atacante falsificar la so dirección IP como visible pa ownCloud . Más información puede atopase na nuesa documentación.", + "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 memcached wiki about both modules." : "Memcached configúrase como caché distribuyida, pero instalóse'l módulu de PHP \"Memcache\" equivocáu. \\OC\\Memcache\\Memcached namás almite \"memcached\" y non \"memcache\". Vea la wiki memcached sobre ambos módulos .", + "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our documentation. (List of invalid files… / Rescan…)" : "Dellos arquivos nun pasaron la comprobación d'integridá. Pues atopas más información sobre cómo resolver esti problema na nuesa documentation. ( Llista de ficheros non válidos.../ Volver a guetar…)", + "Error occurred while checking server setup" : "Asocedió un fallu mientres se comprobaba la configuración del sirvidor", + "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "El direutoriu de datos y ficheros ye dablemente accesible dende Internet, darréu que'l ficheru .htaccess nun ta funcionando. Suxerímoste que configures el sirvidor web de mou que'l direutoriu de datos nun seya accesible o que muevas talu direutoriu fuera del raigañu de documentos del sirvidor web.", + "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "La \"{header}\" HTTP nun ta configurada pa igualar a \"{expected}\". Esto ye una seguridá o privacidá potencial de riesgu y encamentamos axustar esta opción.", + "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "La cabecera HTTP \"Estrictu-Tresporte-Seguridá\" nun ta configurada pa siquier \"{seconds}\" segundos. Pa mayor seguridá encamentámos-y habilitar HSTS como se describe en nuesos conseyos de seguridá.", + "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Tas ingresando a esti sitiu vía HTTP. Encamentámoste que configures el sirvidor pa solicitar HTTPS como describimos en nuesos conseyos de seguridá.", "Shared" : "Compartíu", "Shared with {recipients}" : "Compartío con {recipients}", "Error" : "Fallu", @@ -152,6 +164,7 @@ OC.L10N.register( "Send" : "Unviar", "Sending ..." : "Unviando ...", "Email sent" : "Corréu unviáu", + "Send link via email" : "Unviáu enllaz por email", "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", @@ -164,17 +177,44 @@ OC.L10N.register( "change" : "camudar", "delete" : "desaniciar", "access control" : "control d'accesu", + "Could not unshare" : "Nun pudo dexase de compartir", + "Share details could not be loaded for this item." : "Los detalles de les acciones nun pudieron cargase por esti elementu.", + "No users or groups found for {search}" : "Nun s'atopó nengún usuariu o grupu por {search}", + "No users found for {search}" : "Nun s'atoparon usuarios por {search}", + "An error occurred. Please try again" : "Hebo un fallu. Por favor, inténtalo de nueves", + "{sharee} (group)" : "{sharee} (grupu)", + "{sharee} (at {server})" : "{sharee} (en {server})", + "{sharee} (remote)" : "{sharee} (remotu)", "Share" : "Compartir", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Compartir con xente d'otros ownClouds usando la sintaxis usuariu@exemplu.com/owncloud", + "Share with users…" : "Compartir con usuarios...", + "Share with users, groups or remote users…" : "Compartir con usuarios, grupos o usuarios remotos...", + "Share with users or groups…" : "Compartir con usuarios o grupos...", + "Share with users or remote users…" : "Compartir con usuarios o usuarios remotos...", + "Error removing share" : "Fallu desaniciando compartición", "Warning" : "Avisu", + "Error while sending notification" : "Fallu mientres s'unviaba la notificación", + "Non-existing tag #{tag}" : "Nun esiste la etiqueta #{tag}", + "restricted" : "torgáu", + "invisible" : "invisible", + "({scope})" : "({scope})", "Delete" : "Desaniciar", "Rename" : "Renomar", + "Collaborative tags" : "Etiquetes colaboratives", "The object type is not specified." : "El tipu d'oxetu nun ta especificáu.", "Enter new" : "Introducir nueva", "Add" : "Amestar", "Edit tags" : "Editar etiquetes", "Error loading dialog template: {error}" : "Fallu cargando plantía de diálogu: {error}", "No tags selected for deletion." : "Nun s'esbillaron etiquetes pa desaniciar.", + "unknown text" : "testu desconocíu", + "Hello world!" : "¡Hola mundiu!", + "sunny" : "soleyeru", + "Hello {name}, the weather is {weather}" : "Hola {name}, el tiempu ta {weather}", + "Hello {name}" : "Hola {name}", + "new" : "nuevu", + "_download %n file_::_download %n files_" : ["descargando %n ficheru","descargando %n ficheros"], + "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "L'actualización ta en cursu, salir d'esta páxina podría atayar el procesu en dellos entornos.", "Please reload the page." : "Por favor, recarga la páxina", "The update was unsuccessful. Please report this issue to the ownCloud community." : "L'anovamientu fízose con ésitu. Por favor, informa d'esti problema a la comuña ownCloud.", "The update was successful. Redirecting you to ownCloud now." : "L'anovamientu fízose con ésitu. Redirixiendo agora al to ownCloud.", diff --git a/core/l10n/ast.json b/core/l10n/ast.json index 2f80bfb774172..ac640aac2049c 100644 --- a/core/l10n/ast.json +++ b/core/l10n/ast.json @@ -129,6 +129,18 @@ "Strong password" : "Contraseña mui bona", "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "El to sirvidor web entá nun ta configuráu afayadizamente pa permitir la sincronización de ficheros porque la interfaz WebDAV paez tar rota.", "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our documentation." : "El to sirvidor web nun ta configuráu correchamente pa resolver \"{url}\". Pues atopar más información en nuesa documentación .", + "This server has no working Internet connection. 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. We suggest to enable Internet connection for this server if you want to have all features." : "Esti sirvidor nun tien conexón a Internet. Esto significa que dalgunes de les carauterístiques nun van funcionar, como'l montaxe d'almacenamiento esternu, les notificaciones sobre anovamientos, la instalación d'aplicaciones de terceros, l'accesu a los ficheros de mou remotu o l'unviu de correos-e de notificación. Suxerimos habilitar una conexón a Internet nesti sirvidor pa esfrutar de toles funciones.", + "No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our documentation." : "Configuróse ensin la memoria caché. P'ameyorar el so rendimientu configure un Memcache si ta disponible. Puede atopar más información na nuesa documentación.", + "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our documentation." : "/dev/urandom nun ye llexible por PHP que amás nun ye recomendable por razones de seguridá. Pues atopar más información na nuesa documentación.", + "You are currently running PHP {version}. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by the PHP Group as soon as your distribution supports it." : "Ta executándose anguaño la {version} PHP. Convidamoste a actualizar la to versión PHP p'aprovechate del rendimientu y actualizaciones de seguridá proporcionaes pol Grupu PHP desque la so distribución sofitelo.", + "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our documentation." : "La configuración de les cabeceres de proxy inverses ye incorrecta , o tas aportando ownCloud dende un proxy d'enfotu . Si nun tas aportando a ownCloud dende un proxy d'enfotu, esto ye un problema de seguridá y puede dexar a un atacante falsificar la so dirección IP como visible pa ownCloud . Más información puede atopase na nuesa documentación.", + "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 memcached wiki about both modules." : "Memcached configúrase como caché distribuyida, pero instalóse'l módulu de PHP \"Memcache\" equivocáu. \\OC\\Memcache\\Memcached namás almite \"memcached\" y non \"memcache\". Vea la wiki memcached sobre ambos módulos .", + "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our documentation. (List of invalid files… / Rescan…)" : "Dellos arquivos nun pasaron la comprobación d'integridá. Pues atopas más información sobre cómo resolver esti problema na nuesa documentation. ( Llista de ficheros non válidos.../ Volver a guetar…)", + "Error occurred while checking server setup" : "Asocedió un fallu mientres se comprobaba la configuración del sirvidor", + "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "El direutoriu de datos y ficheros ye dablemente accesible dende Internet, darréu que'l ficheru .htaccess nun ta funcionando. Suxerímoste que configures el sirvidor web de mou que'l direutoriu de datos nun seya accesible o que muevas talu direutoriu fuera del raigañu de documentos del sirvidor web.", + "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "La \"{header}\" HTTP nun ta configurada pa igualar a \"{expected}\". Esto ye una seguridá o privacidá potencial de riesgu y encamentamos axustar esta opción.", + "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "La cabecera HTTP \"Estrictu-Tresporte-Seguridá\" nun ta configurada pa siquier \"{seconds}\" segundos. Pa mayor seguridá encamentámos-y habilitar HSTS como se describe en nuesos conseyos de seguridá.", + "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Tas ingresando a esti sitiu vía HTTP. Encamentámoste que configures el sirvidor pa solicitar HTTPS como describimos en nuesos conseyos de seguridá.", "Shared" : "Compartíu", "Shared with {recipients}" : "Compartío con {recipients}", "Error" : "Fallu", @@ -150,6 +162,7 @@ "Send" : "Unviar", "Sending ..." : "Unviando ...", "Email sent" : "Corréu unviáu", + "Send link via email" : "Unviáu enllaz por email", "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", @@ -162,17 +175,44 @@ "change" : "camudar", "delete" : "desaniciar", "access control" : "control d'accesu", + "Could not unshare" : "Nun pudo dexase de compartir", + "Share details could not be loaded for this item." : "Los detalles de les acciones nun pudieron cargase por esti elementu.", + "No users or groups found for {search}" : "Nun s'atopó nengún usuariu o grupu por {search}", + "No users found for {search}" : "Nun s'atoparon usuarios por {search}", + "An error occurred. Please try again" : "Hebo un fallu. Por favor, inténtalo de nueves", + "{sharee} (group)" : "{sharee} (grupu)", + "{sharee} (at {server})" : "{sharee} (en {server})", + "{sharee} (remote)" : "{sharee} (remotu)", "Share" : "Compartir", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Compartir con xente d'otros ownClouds usando la sintaxis usuariu@exemplu.com/owncloud", + "Share with users…" : "Compartir con usuarios...", + "Share with users, groups or remote users…" : "Compartir con usuarios, grupos o usuarios remotos...", + "Share with users or groups…" : "Compartir con usuarios o grupos...", + "Share with users or remote users…" : "Compartir con usuarios o usuarios remotos...", + "Error removing share" : "Fallu desaniciando compartición", "Warning" : "Avisu", + "Error while sending notification" : "Fallu mientres s'unviaba la notificación", + "Non-existing tag #{tag}" : "Nun esiste la etiqueta #{tag}", + "restricted" : "torgáu", + "invisible" : "invisible", + "({scope})" : "({scope})", "Delete" : "Desaniciar", "Rename" : "Renomar", + "Collaborative tags" : "Etiquetes colaboratives", "The object type is not specified." : "El tipu d'oxetu nun ta especificáu.", "Enter new" : "Introducir nueva", "Add" : "Amestar", "Edit tags" : "Editar etiquetes", "Error loading dialog template: {error}" : "Fallu cargando plantía de diálogu: {error}", "No tags selected for deletion." : "Nun s'esbillaron etiquetes pa desaniciar.", + "unknown text" : "testu desconocíu", + "Hello world!" : "¡Hola mundiu!", + "sunny" : "soleyeru", + "Hello {name}, the weather is {weather}" : "Hola {name}, el tiempu ta {weather}", + "Hello {name}" : "Hola {name}", + "new" : "nuevu", + "_download %n file_::_download %n files_" : ["descargando %n ficheru","descargando %n ficheros"], + "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "L'actualización ta en cursu, salir d'esta páxina podría atayar el procesu en dellos entornos.", "Please reload the page." : "Por favor, recarga la páxina", "The update was unsuccessful. Please report this issue to the ownCloud community." : "L'anovamientu fízose con ésitu. Por favor, informa d'esti problema a la comuña ownCloud.", "The update was successful. Redirecting you to ownCloud now." : "L'anovamientu fízose con ésitu. Redirixiendo agora al to ownCloud.", diff --git a/core/l10n/da.js b/core/l10n/da.js index e862b3444f49d..bd92f63ea16b0 100644 --- a/core/l10n/da.js +++ b/core/l10n/da.js @@ -29,6 +29,7 @@ OC.L10N.register( "Preparing update" : "Forbereder opdatering", "Repair warning: " : "Reparationsadvarsel:", "Repair error: " : "Reparationsfejl:", + "Please use the command line updater because automatic updating is disabled in the config.php." : "Brug kommandolinje-updateren, da automatisk opdatering er slået fra i config.php", "Turned on maintenance mode" : "Startede vedligeholdelsestilstand", "Turned off maintenance mode" : "standsede vedligeholdelsestilstand", "Maintenance mode is kept active" : "Vedligeholdelsestilstanden holdes kørende", @@ -93,7 +94,9 @@ OC.L10N.register( "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dec.", + "There were problems with the code integrity check. More information…" : "Der var problemer med integritetskontrollen af koden. Mere information...", "Settings" : "Indstillinger", + "Problem loading page, reloading in 5 seconds" : "Problem med indlæsning af side, genindlæser om 5 sekunder", "Saving..." : "Gemmer...", "Dismiss" : "Afvis", "seconds ago" : "sekunder siden", @@ -126,9 +129,16 @@ OC.L10N.register( "Strong password" : "Stærkt kodeord", "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Din webserver er endnu ikke sat korrekt op til at tillade filsynkronisering, fordi WebDAV-grænsefladen ser ud til at være i stykker.", "This server has no working Internet connection. 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. We suggest to enable Internet connection for this server if you want to have all features." : "Denne ownCloud-server har ikke en fungerende forbindelse til internettet. Det betyder, at visse funktioner som montering af eksterne drev, oplysninger om opdatering eller installation af applikationer fra tredjepart ikke fungerer. Det vil sandsynligvis heller ikke være muligt at tilgå filer fra eksterne drev eller afsendelse af e-mail med notifikationer virker sandsynligvis heller ikke. Vi opfordrer til at etablere forbindelse til internettet for denne server, såfremt du ønsker samtlige funktioner.", + "No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our documentation." : "Der er ikke konfigureret noget hukommelsesmellemlager. For at forbedre din ydelse bør du om muligt konfigurere en mamcache. Yderligere information findes i dokumentationen.", + "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our documentation." : "/dev/urandom kan ikke læses af PHP, hvilket stærkt frarådes af sikkerhedsgrunde. Yderligere information kan findes i vores dokumentation.", + "You are currently running PHP {version}. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by the PHP Group as soon as your distribution supports it." : "Du kører i øjeblikket med PHP {version}. Vi anbefaler dig at opgradere din PHP version for at få glæde af ydelses- og sikkerhedsopdateringer udgivet af the PHP Group så snart din dintribution understøtter dem.", + "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our documentation." : "Konfigurationen af reverse proxy-headere er ikke korrekt eller du tilgår ownCloud fra en betroet proxy. Hvis du ikke tilgår ownCloud fra en betroet proxy, så er dette et sikkerhedsproblem og kan tillade en angriber af forfalske deres IP-adresse som synlig for ownCloud. Yderligere information kan findes i vores dokumentation.", + "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 memcached wiki about both modules." : "Memcached er konfigureret som et distribueret mellemlager, men det forkerte PHP-modul \"memcache\" er installeret. \\OC\\Memcache\\Memcached understøtter kun \"memcached\" og ikke \"memcache\". Se memcached-wikien om begge moduler.", + "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our documentation. (List of invalid files… / Rescan…)" : "Nogle filer har ikke bestået integritetskontrollen. Yderligere information om hvordan man løser dette problem kan findes i vores dodumentation. (Liste over ugyldige filer... / Scan igen…)", "Error occurred while checking server setup" : "Der opstod fejl under tjek af serveropsætningen", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Din data mappe og dine filer er muligvis tilgængelige fra internettet. Filen .htaccess fungerer ikke. Vi anbefaler på det kraftigste, at du konfigurerer din webserver således at datamappen ikke længere er tilgængelig, eller at du flytter datamappen uden for webserverens dokumentrod. ", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "HTTP-hovedet \"{header}\" er ikke konfigureret til at være lig med \"{expected}\". Dette er en potentiel sikkerhedsrisiko, og vi anbefaler at du justerer denne indstilling.", + "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "HTTP headeren \"Strict-Transport-Security\" er ikke konfigureret til mindst \"{seconds}\" sekunder. For bedre sikkerhed anbefaler vi at aktivere HSTS som beskrevet i vores sikkerhedstips.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Du tilgår dette sted gennem HTTP. Vi anbefaler kraftigt at du konfigurerer din server, så der kræves brug af HTTPS i stedet for, som foreskrevet i vores sikkerhedstips.", "Shared" : "Delt", "Shared with {recipients}" : "Delt med {recipients}", @@ -151,6 +161,7 @@ OC.L10N.register( "Send" : "Send", "Sending ..." : "Sender ...", "Email sent" : "E-mail afsendt", + "Send link via email" : "Send link via e-mail", "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}", "group" : "gruppe", @@ -163,12 +174,22 @@ OC.L10N.register( "change" : "tilpas", "delete" : "slet", "access control" : "Adgangskontrol", + "Could not unshare" : "Kunne ikke ophæve deling", "Share details could not be loaded for this item." : "Detaljer for deling kunne ikke indlæses for dette element.", + "No users or groups found for {search}" : "Ingen brugere eller grupper fundet for {search}", + "No users found for {search}" : "Ingen brugere fundet for {search}", + "An error occurred. Please try again" : "Der opstor den fejl. Prøv igen", "Share" : "Del", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Del med andre på ownCloud ved hjælp af syntaxen username@example.com/owncloud", + "Share with users…" : "Del med brugere...", + "Share with users, groups or remote users…" : "Del med brugere, grupper eller eksterne brugere...", + "Share with users or groups…" : "Del med brugere eller grupper...", + "Share with users or remote users…" : "Del med brugere eller eksterne brugere...", "Error removing share" : "Fejl ved fjernelse af deling", "Warning" : "Advarsel", "Error while sending notification" : "Fejl ved afsendelse af notifikation", + "Non-existing tag #{tag}" : "Ikke-eksisterende mærke #{tag}", + "restricted" : "begrænset", "invisible" : "usynlig", "Delete" : "Slet", "Rename" : "Omdøb", diff --git a/core/l10n/da.json b/core/l10n/da.json index c5c1775d6dfa7..b4c8b790b580a 100644 --- a/core/l10n/da.json +++ b/core/l10n/da.json @@ -27,6 +27,7 @@ "Preparing update" : "Forbereder opdatering", "Repair warning: " : "Reparationsadvarsel:", "Repair error: " : "Reparationsfejl:", + "Please use the command line updater because automatic updating is disabled in the config.php." : "Brug kommandolinje-updateren, da automatisk opdatering er slået fra i config.php", "Turned on maintenance mode" : "Startede vedligeholdelsestilstand", "Turned off maintenance mode" : "standsede vedligeholdelsestilstand", "Maintenance mode is kept active" : "Vedligeholdelsestilstanden holdes kørende", @@ -91,7 +92,9 @@ "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dec.", + "There were problems with the code integrity check. More information…" : "Der var problemer med integritetskontrollen af koden. Mere information...", "Settings" : "Indstillinger", + "Problem loading page, reloading in 5 seconds" : "Problem med indlæsning af side, genindlæser om 5 sekunder", "Saving..." : "Gemmer...", "Dismiss" : "Afvis", "seconds ago" : "sekunder siden", @@ -124,9 +127,16 @@ "Strong password" : "Stærkt kodeord", "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Din webserver er endnu ikke sat korrekt op til at tillade filsynkronisering, fordi WebDAV-grænsefladen ser ud til at være i stykker.", "This server has no working Internet connection. 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. We suggest to enable Internet connection for this server if you want to have all features." : "Denne ownCloud-server har ikke en fungerende forbindelse til internettet. Det betyder, at visse funktioner som montering af eksterne drev, oplysninger om opdatering eller installation af applikationer fra tredjepart ikke fungerer. Det vil sandsynligvis heller ikke være muligt at tilgå filer fra eksterne drev eller afsendelse af e-mail med notifikationer virker sandsynligvis heller ikke. Vi opfordrer til at etablere forbindelse til internettet for denne server, såfremt du ønsker samtlige funktioner.", + "No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our documentation." : "Der er ikke konfigureret noget hukommelsesmellemlager. For at forbedre din ydelse bør du om muligt konfigurere en mamcache. Yderligere information findes i dokumentationen.", + "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our documentation." : "/dev/urandom kan ikke læses af PHP, hvilket stærkt frarådes af sikkerhedsgrunde. Yderligere information kan findes i vores dokumentation.", + "You are currently running PHP {version}. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by the PHP Group as soon as your distribution supports it." : "Du kører i øjeblikket med PHP {version}. Vi anbefaler dig at opgradere din PHP version for at få glæde af ydelses- og sikkerhedsopdateringer udgivet af the PHP Group så snart din dintribution understøtter dem.", + "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our documentation." : "Konfigurationen af reverse proxy-headere er ikke korrekt eller du tilgår ownCloud fra en betroet proxy. Hvis du ikke tilgår ownCloud fra en betroet proxy, så er dette et sikkerhedsproblem og kan tillade en angriber af forfalske deres IP-adresse som synlig for ownCloud. Yderligere information kan findes i vores dokumentation.", + "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 memcached wiki about both modules." : "Memcached er konfigureret som et distribueret mellemlager, men det forkerte PHP-modul \"memcache\" er installeret. \\OC\\Memcache\\Memcached understøtter kun \"memcached\" og ikke \"memcache\". Se memcached-wikien om begge moduler.", + "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our documentation. (List of invalid files… / Rescan…)" : "Nogle filer har ikke bestået integritetskontrollen. Yderligere information om hvordan man løser dette problem kan findes i vores dodumentation. (Liste over ugyldige filer... / Scan igen…)", "Error occurred while checking server setup" : "Der opstod fejl under tjek af serveropsætningen", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Din data mappe og dine filer er muligvis tilgængelige fra internettet. Filen .htaccess fungerer ikke. Vi anbefaler på det kraftigste, at du konfigurerer din webserver således at datamappen ikke længere er tilgængelig, eller at du flytter datamappen uden for webserverens dokumentrod. ", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "HTTP-hovedet \"{header}\" er ikke konfigureret til at være lig med \"{expected}\". Dette er en potentiel sikkerhedsrisiko, og vi anbefaler at du justerer denne indstilling.", + "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "HTTP headeren \"Strict-Transport-Security\" er ikke konfigureret til mindst \"{seconds}\" sekunder. For bedre sikkerhed anbefaler vi at aktivere HSTS som beskrevet i vores sikkerhedstips.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Du tilgår dette sted gennem HTTP. Vi anbefaler kraftigt at du konfigurerer din server, så der kræves brug af HTTPS i stedet for, som foreskrevet i vores sikkerhedstips.", "Shared" : "Delt", "Shared with {recipients}" : "Delt med {recipients}", @@ -149,6 +159,7 @@ "Send" : "Send", "Sending ..." : "Sender ...", "Email sent" : "E-mail afsendt", + "Send link via email" : "Send link via e-mail", "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}", "group" : "gruppe", @@ -161,12 +172,22 @@ "change" : "tilpas", "delete" : "slet", "access control" : "Adgangskontrol", + "Could not unshare" : "Kunne ikke ophæve deling", "Share details could not be loaded for this item." : "Detaljer for deling kunne ikke indlæses for dette element.", + "No users or groups found for {search}" : "Ingen brugere eller grupper fundet for {search}", + "No users found for {search}" : "Ingen brugere fundet for {search}", + "An error occurred. Please try again" : "Der opstor den fejl. Prøv igen", "Share" : "Del", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Del med andre på ownCloud ved hjælp af syntaxen username@example.com/owncloud", + "Share with users…" : "Del med brugere...", + "Share with users, groups or remote users…" : "Del med brugere, grupper eller eksterne brugere...", + "Share with users or groups…" : "Del med brugere eller grupper...", + "Share with users or remote users…" : "Del med brugere eller eksterne brugere...", "Error removing share" : "Fejl ved fjernelse af deling", "Warning" : "Advarsel", "Error while sending notification" : "Fejl ved afsendelse af notifikation", + "Non-existing tag #{tag}" : "Ikke-eksisterende mærke #{tag}", + "restricted" : "begrænset", "invisible" : "usynlig", "Delete" : "Slet", "Rename" : "Omdøb", diff --git a/settings/l10n/nl.js b/settings/l10n/nl.js index b9036f53b8317..78163d592c00a 100644 --- a/settings/l10n/nl.js +++ b/settings/l10n/nl.js @@ -278,6 +278,7 @@ OC.L10N.register( "Name" : "Naam", "App name" : "App naam", "Create new app password" : "Creëer nieuw app wachtwoord", + "Use the credentials below to configure your app or device." : "Gebruik onderstaande inloggegevens om uw app of apparaat te configureren.", "Username" : "Gebruikersnaam", "Done" : "Gedaan", "Get the apps to sync your files" : "Download de apps om bestanden te synchroniseren", diff --git a/settings/l10n/nl.json b/settings/l10n/nl.json index 474e657f320dc..a4e1aa2ccba05 100644 --- a/settings/l10n/nl.json +++ b/settings/l10n/nl.json @@ -276,6 +276,7 @@ "Name" : "Naam", "App name" : "App naam", "Create new app password" : "Creëer nieuw app wachtwoord", + "Use the credentials below to configure your app or device." : "Gebruik onderstaande inloggegevens om uw app of apparaat te configureren.", "Username" : "Gebruikersnaam", "Done" : "Gedaan", "Get the apps to sync your files" : "Download de apps om bestanden te synchroniseren", From 7ea089321275b4ae5ed8d04f8094a9f93fe7e671 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 1 Jul 2016 13:33:00 +0200 Subject: [PATCH 60/81] Do not allow directory traversal using "../" We should not allow directory traversals using "../" here. To test access the following URL once with and then without this patch: http://localhost/server/index.php/apps/files/?dir=../../This+Should+Not+Be+Here --- apps/files/js/filelist.js | 2 +- apps/files/tests/js/filelistSpec.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index e483882fcc56b..1f19c2a6258a9 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1404,7 +1404,7 @@ * @param {string} [fileId] file id */ _setCurrentDir: function(targetDir, changeUrl, fileId) { - targetDir = targetDir.replace(/\\/g, '/'); + targetDir = targetDir.replace(/\\/g, '/').replace(/\.\.\//g, ''); var previousDir = this.getCurrentDirectory(), baseDir = OC.basename(targetDir); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index ae4b75f77712d..baf071af9bda3 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -1334,6 +1334,10 @@ describe('OCA.Files.FileList tests', function() { fileList.changeDirectory('/another\\subdir'); expect(fileList.getCurrentDirectory()).toEqual('/another/subdir'); }); + it('converts backslashes to slashes and removes traversals when calling changeDirectory()', function() { + fileList.changeDirectory('/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../'); + expect(fileList.getCurrentDirectory()).toEqual('/another/subdir/foo/bar/file/folder/'); + }); it('switches to root dir when current directory does not exist', function() { fileList.changeDirectory('/unexist'); deferredList.reject(404); From b09f872598ad59d95f7b84824d0183ceae00a21d Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 1 Jul 2016 15:00:31 +0200 Subject: [PATCH 61/81] Match for /../ --- apps/files/js/filelist.js | 2 +- apps/files/tests/js/filelistSpec.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 1f19c2a6258a9..506d423c817b8 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1404,7 +1404,7 @@ * @param {string} [fileId] file id */ _setCurrentDir: function(targetDir, changeUrl, fileId) { - targetDir = targetDir.replace(/\\/g, '/').replace(/\.\.\//g, ''); + targetDir = targetDir.replace(/\\/g, '/').replace(/\/\.\.\//g, '/'); var previousDir = this.getCurrentDirectory(), baseDir = OC.basename(targetDir); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index baf071af9bda3..a9b6a1ac1c82d 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -1338,6 +1338,10 @@ describe('OCA.Files.FileList tests', function() { fileList.changeDirectory('/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../'); expect(fileList.getCurrentDirectory()).toEqual('/another/subdir/foo/bar/file/folder/'); }); + it('does not convert folders with a ".." in the name', function() { + fileList.changeDirectory('/abc../def'); + expect(fileList.getCurrentDirectory()).toEqual('/abc../def'); + }); it('switches to root dir when current directory does not exist', function() { fileList.changeDirectory('/unexist'); deferredList.reject(404); From f18f4d06b0dd22b53ba26c7fb7f481f7dd5c8dcd Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 1 Jul 2016 15:19:08 +0200 Subject: [PATCH 62/81] Match on 405 --- apps/files/js/filelist.js | 2 +- apps/files/tests/js/filelistSpec.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 506d423c817b8..0813d2cc30e6f 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1552,7 +1552,7 @@ return false; } - if (status === 404) { + if (status === 404 || status === 405) { // go back home this.changeDirectory('/'); return false; diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index a9b6a1ac1c82d..453f1cafcafcd 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -1347,6 +1347,11 @@ describe('OCA.Files.FileList tests', function() { deferredList.reject(404); expect(fileList.getCurrentDirectory()).toEqual('/'); }); + it('switches to root dir when current directory returns 405', function() { + fileList.changeDirectory('/unexist'); + deferredList.reject(405); + expect(fileList.getCurrentDirectory()).toEqual('/'); + }); it('switches to root dir when current directory is forbidden', function() { fileList.changeDirectory('/unexist'); deferredList.reject(403); From b98ecd8939bbdc43b606964490750c5431664f7b Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Fri, 1 Jul 2016 15:28:13 +0200 Subject: [PATCH 63/81] update to 3rdparty master --- 3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index 46668812ff12d..1389370747483 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 46668812ff12d320ba207f120bd50acffa6e7748 +Subproject commit 138937074748316800e74cabbc59f681e2e52d2f From c79cf5b8bc17bf03be9df4c5bdba8d73f026e142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Bl=C3=BCm?= Date: Sat, 2 Jul 2016 14:21:01 +0200 Subject: [PATCH 64/81] We have our own Transifex org now ;) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 952fad734ba10..64cad6ba647be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,4 +38,4 @@ In some areas unit testing is hard (aka almost impossible) as of today - in thes ## Translations Please submit translations via [Transifex][transifex]. -[transifex]: https://www.transifex.com/projects/p/owncloud/ +[transifex]: https://www.transifex.com/nextcloud From 27c2b7a0282a0bc0e18a3f7ac41675938b7a0595 Mon Sep 17 00:00:00 2001 From: Alexander Yamshanov Date: Sun, 3 Jul 2016 15:13:08 +0600 Subject: [PATCH 65/81] Add mimetype for fb2-extension --- resources/config/mimetypealiases.dist.json | 1 + resources/config/mimetypemapping.dist.json | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/config/mimetypealiases.dist.json b/resources/config/mimetypealiases.dist.json index 2a1e8485780ec..8445198e32c1b 100644 --- a/resources/config/mimetypealiases.dist.json +++ b/resources/config/mimetypealiases.dist.json @@ -61,6 +61,7 @@ "application/x-compressed": "package/x-generic", "application/x-dcraw": "image", "application/x-deb": "package/x-generic", + "application/x-fictionbook+xml": "text", "application/x-font": "image", "application/x-gimp": "image", "application/x-gzip": "package/x-generic", diff --git a/resources/config/mimetypemapping.dist.json b/resources/config/mimetypemapping.dist.json index 16f5027d62608..00c4e8bf12f2d 100644 --- a/resources/config/mimetypemapping.dist.json +++ b/resources/config/mimetypemapping.dist.json @@ -52,6 +52,7 @@ "eps": ["application/postscript"], "erf": ["image/x-dcraw"], "exe": ["application/x-ms-dos-executable"], + "fb2": ["application/x-fictionbook+xml", "text/plain"], "flac": ["audio/flac"], "flv": ["video/x-flv"], "gif": ["image/gif"], From 0e0148f1c84a332889ba22626f4fba4bbabfbf17 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sun, 3 Jul 2016 16:54:41 +0200 Subject: [PATCH 66/81] [master] Use paramterized parameter for \OC\SystemTag\SystemTagManager $nameSearchPattern was passed in and directly appended to the SQL query. Luckily the code path isn't reached anywhere in Nextcloud or the included apps. --- lib/private/SystemTag/SystemTagManager.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php index 2b0ef03e471d0..3e32582025f59 100644 --- a/lib/private/SystemTag/SystemTagManager.php +++ b/lib/private/SystemTag/SystemTagManager.php @@ -140,10 +140,7 @@ public function getAllTags($visibilityFilter = null, $nameSearchPattern = null) if (!empty($nameSearchPattern)) { $query->andWhere( - $query->expr()->like( - 'name', - $query->expr()->literal('%' . $this->connection->escapeLikeParameter($nameSearchPattern). '%') - ) + $query->expr()->like('name', $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($nameSearchPattern) . '%')) ); } From ebda6df1e28f8d2e1a113746614dca7d6fcbc4dc Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 4 Jul 2016 10:40:13 +0200 Subject: [PATCH 67/81] Collapse logs and lists with HTML5 support of github --- issue_template.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/issue_template.md b/issue_template.md index a17628377b1ce..94aad9a5b0b67 100644 --- a/issue_template.md +++ b/issue_template.md @@ -34,22 +34,30 @@ Tell us what happens instead **Where did you install Nextcloud from:** **Signing status (Nextcloud 9.0 and above):** +
+Signing status ``` Login as admin user into your Nextcloud and access http://example.com/index.php/settings/integrity/failed paste the results here. ``` +
**List of activated apps:** +
+App list ``` If you have access to your command line run e.g.: sudo -u www-data php occ app:list from within your Nextcloud installation folder ``` +
**The content of config/config.php:** +
+Config report ``` If you have access to your command line run e.g.: @@ -61,6 +69,7 @@ or Insert your config.php content here (Without the database password, passwordsalt and secret) ``` +
**Are you using external storage, if yes which one:** local/smb/sftp/... @@ -69,6 +78,8 @@ Insert your config.php content here **Are you using an external user-backend, if yes which one:** LDAP/ActiveDirectory/Webdav/... #### LDAP configuration (delete this part if not used) +
+LDAP config ``` With access to your command line run e.g.: @@ -82,6 +93,7 @@ SELECT * FROM `oc_appconfig` WHERE `appid` = 'user_ldap'; Eventually replace sensitive data as the name/IP-address of your LDAP server or groups. ``` +
### Client configuration **Browser:** @@ -90,20 +102,29 @@ Eventually replace sensitive data as the name/IP-address of your LDAP server or ### Logs #### Web server error log +
+Browser log ``` Insert your webserver log here ``` +
#### Nextcloud log (data/owncloud.log) +
+Browser log ``` Insert your Nextcloud log here ``` +
#### Browser log +
+Browser log ``` Insert your browser log here, this could for example include: a) The javascript console log -b) The network log +b) The network log c) ... ``` +
From 2cf45308dd930c1710621012d7fbcd354faef697 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 1 Jul 2016 18:48:48 +0200 Subject: [PATCH 68/81] we don't need to check permissions twice --- apps/files_versions/lib/Storage.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index 9a0fe0a7b378e..f0cd9d6531052 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -313,6 +313,7 @@ public static function renameOrCopy($sourcePath, $targetPath, $operation) { * * @param string $file file name * @param int $revision revision timestamp + * @return bool */ public static function rollback($file, $revision) { @@ -323,13 +324,10 @@ public static function rollback($file, $revision) { if ($uid === null || trim($filename, '/') === '') { return false; } + $users_view = new View('/'.$uid); $files_view = new View('/'. User::getUser().'/files'); - if (!$files_view->isUpdatable($filename)) { - return false; - } - $versionCreated = false; $fileInfo = $files_view->getFileInfo($file); From 65a4057b2f74254a1d6f281f481b9b9b0e371a0b Mon Sep 17 00:00:00 2001 From: Thomas Pulzer Date: Mon, 4 Jul 2016 11:50:32 +0200 Subject: [PATCH 69/81] Changed name of default logfile from owncloud.log to nextcloud.log. --- apps/dav/tests/travis/caldav/script.sh | 2 +- apps/dav/tests/travis/carddav/script.sh | 2 +- build/integration/run.sh | 2 +- config/config.sample.php | 6 +++--- core/Command/Log/OwnCloud.php | 2 +- core/Command/Upgrade.php | 2 +- issue_template.md | 2 +- lib/base.php | 4 ++-- lib/private/Log/Owncloud.php | 4 ++-- tests/Core/Command/Log/OwnCloudTest.php | 4 ++-- tests/lib/TestCase.php | 2 +- tests/travis/install.sh | 6 +++--- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/apps/dav/tests/travis/caldav/script.sh b/apps/dav/tests/travis/caldav/script.sh index 7259372567cd0..636235349c504 100644 --- a/apps/dav/tests/travis/caldav/script.sh +++ b/apps/dav/tests/travis/caldav/script.sh @@ -16,6 +16,6 @@ PYTHONPATH="$SCRIPTPATH/pycalendar/src" python testcaldav.py --print-details-onf RESULT=$? -tail "$/../../../../../data-autotest/owncloud.log" +tail "$/../../../../../data-autotest/nextcloud.log" exit $RESULT diff --git a/apps/dav/tests/travis/carddav/script.sh b/apps/dav/tests/travis/carddav/script.sh index a8bd9f11b38df..ecdc0f9586359 100644 --- a/apps/dav/tests/travis/carddav/script.sh +++ b/apps/dav/tests/travis/carddav/script.sh @@ -17,6 +17,6 @@ PYTHONPATH="$SCRIPTPATH/pycalendar/src" python testcaldav.py --print-details-onf RESULT=$? -tail "$/../../../../../data-autotest/owncloud.log" +tail "$/../../../../../data-autotest/nextcloud.log" exit $RESULT diff --git a/build/integration/run.sh b/build/integration/run.sh index 3725ba1af6fca..2abceaa1fad62 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -40,7 +40,7 @@ kill $PHPPID kill $PHPPID_FED if [ -z $HIDE_OC_LOGS ]; then - tail "../../data/owncloud.log" + tail "../../data/nextcloud.log" fi exit $RESULT diff --git a/config/config.sample.php b/config/config.sample.php index 512a5d05ba7f2..6285e096ba799 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -549,7 +549,7 @@ */ /** - * By default the Nextcloud logs are sent to the ``owncloud.log`` file in the + * By default the Nextcloud logs are sent to the ``nextcloud.log`` file in the * default Nextcloud data directory. * If syslogging is desired, set this parameter to ``syslog``. * Setting this parameter to ``errorlog`` will use the PHP error_log function @@ -559,9 +559,9 @@ /** * Log file path for the Nextcloud logging type. - * Defaults to ``[datadirectory]/owncloud.log`` + * Defaults to ``[datadirectory]/nextcloud.log`` */ -'logfile' => '/var/log/owncloud.log', +'logfile' => '/var/log/nextcloud.log', /** * Loglevel to start logging at. Valid values are: 0 = Debug, 1 = Info, 2 = diff --git a/core/Command/Log/OwnCloud.php b/core/Command/Log/OwnCloud.php index 7213f6726a2c0..b469f2064f78e 100644 --- a/core/Command/Log/OwnCloud.php +++ b/core/Command/Log/OwnCloud.php @@ -95,7 +95,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln('Log backend ownCloud: '.$enabledText); $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data'); - $defaultLogFile = rtrim($dataDir, '/').'/owncloud.log'; + $defaultLogFile = rtrim($dataDir, '/').'/nextcloud.log'; $output->writeln('Log file: '.$this->config->getSystemValue('logfile', $defaultLogFile)); $rotateSize = $this->config->getSystemValue('log_rotate_size', 0); diff --git a/core/Command/Upgrade.php b/core/Command/Upgrade.php index 61b2e59a353f6..3550271fb5b05 100644 --- a/core/Command/Upgrade.php +++ b/core/Command/Upgrade.php @@ -300,7 +300,7 @@ function ($success) use($output, $updateStepEnabled, $self) { //Possible scenario: ownCloud core is updated but an app failed $output->writeln('ownCloud is in maintenance mode'); $output->write('Maybe an upgrade is already in process. Please check the ' - . 'logfile (data/owncloud.log). If you want to re-run the ' + . 'logfile (data/nextcloud.log). If you want to re-run the ' . 'upgrade procedure, remove the "maintenance mode" from ' . 'config.php and call this script again.' , true); diff --git a/issue_template.md b/issue_template.md index a17628377b1ce..b18401c506093 100644 --- a/issue_template.md +++ b/issue_template.md @@ -94,7 +94,7 @@ Eventually replace sensitive data as the name/IP-address of your LDAP server or Insert your webserver log here ``` -#### Nextcloud log (data/owncloud.log) +#### Nextcloud log (data/nextcloud.log) ``` Insert your Nextcloud log here ``` diff --git a/lib/base.php b/lib/base.php index 9e5304b163436..dde8e38218afd 100644 --- a/lib/base.php +++ b/lib/base.php @@ -754,8 +754,8 @@ public static function registerLogRotate() { $systemConfig = \OC::$server->getSystemConfig(); if ($systemConfig->getValue('installed', false) && $systemConfig->getValue('log_rotate_size', false) && !self::checkUpgrade(false)) { //don't try to do this before we are properly setup - //use custom logfile path if defined, otherwise use default of owncloud.log in data directory - \OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log')); + //use custom logfile path if defined, otherwise use default of nextcloud.log in data directory + \OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/nextcloud.log')); } } diff --git a/lib/private/Log/Owncloud.php b/lib/private/Log/Owncloud.php index 07106be22b159..d76145ebdd358 100644 --- a/lib/private/Log/Owncloud.php +++ b/lib/private/Log/Owncloud.php @@ -33,7 +33,7 @@ /** * logging utilities * - * Log is saved at data/owncloud.log (on default) + * Log is saved at data/nextcloud.log (on default) */ class Owncloud { @@ -44,7 +44,7 @@ class Owncloud { */ public static function init() { $systemConfig = \OC::$server->getSystemConfig(); - $defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/owncloud.log'; + $defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/nextcloud.log'; self::$logFile = $systemConfig->getValue("logfile", $defaultLogFile); /** diff --git a/tests/Core/Command/Log/OwnCloudTest.php b/tests/Core/Command/Log/OwnCloudTest.php index 3cb05221c37ce..e0445a5cfda9f 100644 --- a/tests/Core/Command/Log/OwnCloudTest.php +++ b/tests/Core/Command/Log/OwnCloudTest.php @@ -101,7 +101,7 @@ public function testGetConfiguration() { ->will($this->returnValueMap([ ['log_type', 'owncloud', 'log_type_value'], ['datadirectory', \OC::$SERVERROOT.'/data', '/data/directory/'], - ['logfile', '/data/directory/owncloud.log', '/var/log/owncloud.log'], + ['logfile', '/data/directory/nextcloud.log', '/var/log/nextcloud.log'], ['log_rotate_size', 0, 5 * 1024 * 1024], ])); @@ -110,7 +110,7 @@ public function testGetConfiguration() { ->with('Log backend ownCloud: disabled'); $this->consoleOutput->expects($this->at(1)) ->method('writeln') - ->with('Log file: /var/log/owncloud.log'); + ->with('Log file: /var/log/nextcloud.log'); $this->consoleOutput->expects($this->at(2)) ->method('writeln') ->with('Rotate at: 5 MB'); diff --git a/tests/lib/TestCase.php b/tests/lib/TestCase.php index a1f65f8ac822f..514cb6ea3a5a0 100644 --- a/tests/lib/TestCase.php +++ b/tests/lib/TestCase.php @@ -269,7 +269,7 @@ static protected function tearDownAfterClassCleanFileCache(IQueryBuilder $queryB */ static protected function tearDownAfterClassCleanStrayDataFiles($dataDir) { $knownEntries = array( - 'owncloud.log' => true, + 'nextcloud.log' => true, 'owncloud.db' => true, '.ocdata' => true, '..' => true, diff --git a/tests/travis/install.sh b/tests/travis/install.sh index fe7907f798caa..180e0c634da4f 100755 --- a/tests/travis/install.sh +++ b/tests/travis/install.sh @@ -173,8 +173,8 @@ cat $BASEDIR/config/config.php echo "data directory:" ls -ll $DATADIR -echo "owncloud.log:" -[ -f "$DATADIR/owncloud.log" ] && cat $DATADIR/owncloud.log -[ -f "$BASEDIR/data/owncloud.log" ] && cat $BASEDIR/data/owncloud.log +echo "nextcloud.log:" +[ -f "$DATADIR/nextcloud.log" ] && cat $DATADIR/nextcloud.log +[ -f "$BASEDIR/data/nextcloud.log" ] && cat $BASEDIR/data/nextcloud.log cd $BASEDIR From 5a9ddaa559dbd035e24de4a15e0f2a246357ff2e Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Mon, 4 Jul 2016 11:56:38 +0200 Subject: [PATCH 70/81] Fix summary --- issue_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/issue_template.md b/issue_template.md index 94aad9a5b0b67..f7906700c942f 100644 --- a/issue_template.md +++ b/issue_template.md @@ -103,7 +103,7 @@ Eventually replace sensitive data as the name/IP-address of your LDAP server or ### Logs #### Web server error log
-Browser log +Web server error log ``` Insert your webserver log here ``` @@ -111,7 +111,7 @@ Insert your webserver log here #### Nextcloud log (data/owncloud.log)
-Browser log +Nextcloud log ``` Insert your Nextcloud log here ``` From 31b099c1bc4f412434316ab7bf8e60315b743a25 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 4 Jul 2016 12:02:07 +0200 Subject: [PATCH 71/81] Factor out handling sidebar previews --- apps/files/js/mainfileinfodetailview.js | 88 ++-------------- apps/files/js/sidebarpreviewmanager.js | 105 +++++++++++++++++++ apps/files/lib/Controller/ViewController.php | 1 + 3 files changed, 113 insertions(+), 81 deletions(-) create mode 100644 apps/files/js/sidebarpreviewmanager.js diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js index c586135b9c736..30b2b531df74b 100644 --- a/apps/files/js/mainfileinfodetailview.js +++ b/apps/files/js/mainfileinfodetailview.js @@ -57,6 +57,11 @@ */ _fileActions: null, + /** + * @type {OCA.Files.SidebarPreviewManager} + */ + _previewManager: null, + events: { 'click a.action-favorite': '_onClickFavorite', 'click a.action-default': '_onClickDefaultAction', @@ -81,6 +86,7 @@ if (!this._fileActions) { throw 'Missing required parameter "fileActions"'; } + this._previewManager = new OCA.Files.SidebarPreviewManager(this._fileList); }, _onClickPermalink: function() { @@ -158,7 +164,7 @@ var $container = this.$el.find('.thumbnailContainer'); if (!this.model.isDirectory()) { $iconDiv.addClass('icon-loading icon-32'); - this.loadPreview(this.model.getFullPath(), this.model.get('mimetype'), this.model.get('etag'), $iconDiv, $container, this.model.isImage()); + this._previewManager.loadPreview(this.model, $iconDiv, $container); } else { var iconUrl = this.model.get('icon') || OC.MimeType.getIconUrl('dir'); $iconDiv.css('background-image', 'url("' + iconUrl + '")'); @@ -169,86 +175,6 @@ this.$el.empty(); } this.delegateEvents(); - }, - - loadPreview: function(path, mime, etag, $iconDiv, $container, isImage) { - var maxImageWidth = $container.parent().width() + 50; // 50px for negative margins - var maxImageHeight = maxImageWidth / (16/9); - var smallPreviewSize = 75; - - var isLandscape = function(img) { - return img.width > (img.height * 1.2); - }; - - var isSmall = function(img) { - return (img.width * 1.1) < (maxImageWidth * window.devicePixelRatio); - }; - - var getTargetHeight = function(img) { - if(isImage) { - var targetHeight = img.height / window.devicePixelRatio; - if (targetHeight <= smallPreviewSize) { - targetHeight = smallPreviewSize; - } - return targetHeight; - }else{ - return smallPreviewSize; - } - }; - - var getTargetRatio = function(img){ - var ratio = img.width / img.height; - if (ratio > 16/9) { - return ratio; - } else { - return 16/9; - } - }; - - this._fileList.lazyLoadPreview({ - path: path, - mime: mime, - etag: etag, - y: isImage ? maxImageHeight : smallPreviewSize, - x: isImage ? maxImageWidth : smallPreviewSize, - a: isImage ? 1 : null, - mode: isImage ? 'cover' : null, - callback: function (previewUrl, img) { - $iconDiv.previewImg = previewUrl; - - // as long as we only have the mimetype icon, we only save it in case there is no preview - if (!img) { - return; - } - $iconDiv.removeClass('icon-loading icon-32'); - var targetHeight = getTargetHeight(img); - if (this.model.isImage() && targetHeight > smallPreviewSize) { - $container.addClass((isLandscape(img) && !isSmall(img))? 'landscape': 'portrait'); - $container.addClass('image'); - } - - // only set background when we have an actual preview - // when we don't have a preview we show the mime icon in the error handler - $iconDiv.css({ - 'background-image': 'url("' + previewUrl + '")', - height: (targetHeight > smallPreviewSize)? 'auto': targetHeight, - 'max-height': isSmall(img)? targetHeight: null - }); - - var targetRatio = getTargetRatio(img); - $iconDiv.find('.stretcher').css({ - 'padding-bottom': (100 / targetRatio) + '%' - }); - }.bind(this), - error: function () { - $iconDiv.removeClass('icon-loading icon-32'); - this.$el.find('.thumbnailContainer').removeClass('image'); //fall back to regular view - $iconDiv.css({ - 'background-image': 'url("' + $iconDiv.previewImg + '")' - }); - OC.Util.scaleFixForIE8($iconDiv); - }.bind(this) - }); } }); diff --git a/apps/files/js/sidebarpreviewmanager.js b/apps/files/js/sidebarpreviewmanager.js new file mode 100644 index 0000000000000..5b7906bbb98c3 --- /dev/null +++ b/apps/files/js/sidebarpreviewmanager.js @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +(function () { + SidebarPreviewManager = function (fileList) { + this._fileList = fileList; + }; + + SidebarPreviewManager.prototype = { + loadPreview: function (model, $thumbnailDiv, $thumbnailContainer) { + // todo allow plugins to register custom handlers by mimetype + this.fallbackPreview(model, $thumbnailDiv, $thumbnailContainer); + }, + + // previews for images and mimetype icons + fallbackPreview: function (model, $thumbnailDiv, $thumbnailContainer) { + var isImage = model.isImage(); + var maxImageWidth = $thumbnailContainer.parent().width() + 50; // 50px for negative margins + var maxImageHeight = maxImageWidth / (16 / 9); + var smallPreviewSize = 75; + + var isLandscape = function (img) { + return img.width > (img.height * 1.2); + }; + + var isSmall = function (img) { + return (img.width * 1.1) < (maxImageWidth * window.devicePixelRatio); + }; + + var getTargetHeight = function (img) { + if (isImage) { + var targetHeight = img.height / window.devicePixelRatio; + if (targetHeight <= smallPreviewSize) { + targetHeight = smallPreviewSize; + } + return targetHeight; + } else { + return smallPreviewSize; + } + }; + + var getTargetRatio = function (img) { + var ratio = img.width / img.height; + if (ratio > 16 / 9) { + return ratio; + } else { + return 16 / 9; + } + }; + + this._fileList.lazyLoadPreview({ + path: model.getFullPath(), + mime: model.get('mimetype'), + etag: model.get('etag'), + y: isImage ? maxImageHeight : smallPreviewSize, + x: isImage ? maxImageWidth : smallPreviewSize, + a: isImage ? 1 : null, + mode: isImage ? 'cover' : null, + callback: function (previewUrl, img) { + $thumbnailDiv.previewImg = previewUrl; + + // as long as we only have the mimetype icon, we only save it in case there is no preview + if (!img) { + return; + } + $thumbnailDiv.removeClass('icon-loading icon-32'); + var targetHeight = getTargetHeight(img); + if (isImage && targetHeight > smallPreviewSize) { + $thumbnailContainer.addClass((isLandscape(img) && !isSmall(img)) ? 'landscape' : 'portrait'); + $thumbnailContainer.addClass('image'); + } + + // only set background when we have an actual preview + // when we don't have a preview we show the mime icon in the error handler + $thumbnailDiv.css({ + 'background-image': 'url("' + previewUrl + '")', + height: (targetHeight > smallPreviewSize) ? 'auto' : targetHeight, + 'max-height': isSmall(img) ? targetHeight : null + }); + + var targetRatio = getTargetRatio(img); + $thumbnailDiv.find('.stretcher').css({ + 'padding-bottom': (100 / targetRatio) + '%' + }); + }, + error: function () { + $thumbnailDiv.removeClass('icon-loading icon-32'); + $thumbnailContainer.removeClass('image'); //fall back to regular view + $thumbnailDiv.css({ + 'background-image': 'url("' + $thumbnailDiv.previewImg + '")' + }); + } + }); + } + }; + + OCA.Files.SidebarPreviewManager = SidebarPreviewManager; +})(); diff --git a/apps/files/lib/Controller/ViewController.php b/apps/files/lib/Controller/ViewController.php index 18b6cf719c514..ffa566f4e9be7 100644 --- a/apps/files/lib/Controller/ViewController.php +++ b/apps/files/lib/Controller/ViewController.php @@ -174,6 +174,7 @@ public function index($dir = '', $view = '', $fileid = null) { \OCP\Util::addScript('files', 'favoritesplugin'); \OCP\Util::addScript('files', 'detailfileinfoview'); + \OCP\Util::addScript('files', 'sidebarpreviewmanager'); \OCP\Util::addScript('files', 'detailtabview'); \OCP\Util::addScript('files', 'mainfileinfodetailview'); \OCP\Util::addScript('files', 'detailsview'); From 3b4a5b0857c8b013041bd1b6b9d7ebc6d6e7183b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 4 Jul 2016 12:54:12 +0200 Subject: [PATCH 72/81] Add large sidebar previews for text files --- apps/files/css/detailsView.css | 19 +++++--- apps/files/js/sidebarpreviewmanager.js | 26 +++++++++-- apps/files/js/sidebarpreviewtext.js | 47 ++++++++++++++++++++ apps/files/lib/Controller/ViewController.php | 1 + 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 apps/files/js/sidebarpreviewtext.js diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css index 669a15c4e3898..a49b37e6aaba4 100644 --- a/apps/files/css/detailsView.css +++ b/apps/files/css/detailsView.css @@ -32,17 +32,17 @@ float: left; } -#app-sidebar .thumbnailContainer.image { +#app-sidebar .thumbnailContainer.large { margin-left: -15px; margin-right: -35px; /* 15 + 20 for the close button */ margin-top: -15px; } -#app-sidebar .thumbnailContainer.image.portrait { +#app-sidebar .thumbnailContainer.large.portrait { margin: 0; /* if we don't fit the image anyway we give it back the margin */ } -#app-sidebar .image .thumbnail { +#app-sidebar .large .thumbnail { width:100%; display:block; background-repeat: no-repeat; @@ -53,20 +53,27 @@ height: auto; } -#app-sidebar .image .thumbnail .stretcher { +#app-sidebar .large .thumbnail .stretcher { content: ''; display: block; padding-bottom: 56.25%; /* sets height of .thumbnail to 9/16 of the width */ } -#app-sidebar .image.portrait .thumbnail { +#app-sidebar .large.portrait .thumbnail { background-position: 50% top; } -#app-sidebar .image.portrait .thumbnail { +#app-sidebar .large.portrait .thumbnail { background-size: contain; } +#app-sidebar .text { + overflow-y: scroll; + overflow-x: hidden; + padding-left: 5px; + font-size: 80%; +} + #app-sidebar .thumbnail { width: 75px; height: 75px; diff --git a/apps/files/js/sidebarpreviewmanager.js b/apps/files/js/sidebarpreviewmanager.js index 5b7906bbb98c3..cfd1fffae130f 100644 --- a/apps/files/js/sidebarpreviewmanager.js +++ b/apps/files/js/sidebarpreviewmanager.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 + * Copyright (c) 2016 * * This file is licensed under the Affero General Public License version 3 * or later. @@ -11,12 +11,30 @@ (function () { SidebarPreviewManager = function (fileList) { this._fileList = fileList; + this._previewHandlers = {}; + OC.Plugins.attach('OCA.Files.SidebarPreviewManager', this); }; SidebarPreviewManager.prototype = { + addPreviewHandler: function (mime, handler) { + this._previewHandlers[mime] = handler; + }, + + getPreviewHandler: function (mime) { + var mimePart = mime.split('/').shift(); + if (this._previewHandlers[mime]) { + return this._previewHandlers[mime]; + } else if(this._previewHandlers[mimePart]) { + return this._previewHandlers[mimePart]; + } else { + return this.fallbackPreview.bind(this); + } + }, + loadPreview: function (model, $thumbnailDiv, $thumbnailContainer) { - // todo allow plugins to register custom handlers by mimetype - this.fallbackPreview(model, $thumbnailDiv, $thumbnailContainer); + var handler = this.getPreviewHandler(model.get('mimetype')); + var fallback = this.fallbackPreview.bind(this, model, $thumbnailDiv, $thumbnailContainer); + handler(model, $thumbnailDiv, $thumbnailContainer, fallback); }, // previews for images and mimetype icons @@ -74,7 +92,7 @@ var targetHeight = getTargetHeight(img); if (isImage && targetHeight > smallPreviewSize) { $thumbnailContainer.addClass((isLandscape(img) && !isSmall(img)) ? 'landscape' : 'portrait'); - $thumbnailContainer.addClass('image'); + $thumbnailContainer.addClass('large'); } // only set background when we have an actual preview diff --git a/apps/files/js/sidebarpreviewtext.js b/apps/files/js/sidebarpreviewtext.js new file mode 100644 index 0000000000000..de264ed1e56e6 --- /dev/null +++ b/apps/files/js/sidebarpreviewtext.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +(function () { + var SidebarPreview = function () { + }; + + SidebarPreview.prototype = { + attach: function (manager) { + manager.addPreviewHandler('text', this.handlePreview.bind(this)); + }, + + handlePreview: function (model, $thumbnailDiv, $thumbnailContainer, fallback) { + console.log(model); + var previewWidth = $thumbnailContainer.parent().width() + 50; // 50px for negative margins + var previewHeight = previewWidth / (16 / 9); + + this.getFileContent(model.getFullPath()).then(function (content) { + $thumbnailDiv.removeClass('icon-loading icon-32'); + $thumbnailContainer.addClass('large'); + $thumbnailContainer.addClass('text'); + var $textPreview = $('
').text(content);
+				$thumbnailDiv.children('.stretcher').remove();
+				$thumbnailDiv.append($textPreview);
+				$thumbnailContainer.height(previewHeight);
+			}, function () {
+				fallback();
+			});
+		},
+
+		getFileContent: function (path) {
+			console.log(path);
+			var url = OC.linkToRemoteBase('files' + path);
+			console.log(url);
+			return $.get(url);
+		}
+	};
+
+	OC.Plugins.register('OCA.Files.SidebarPreviewManager', new SidebarPreview());
+})();
diff --git a/apps/files/lib/Controller/ViewController.php b/apps/files/lib/Controller/ViewController.php
index ffa566f4e9be7..30d5bb87f1397 100644
--- a/apps/files/lib/Controller/ViewController.php
+++ b/apps/files/lib/Controller/ViewController.php
@@ -175,6 +175,7 @@ public function index($dir = '', $view = '', $fileid = null) {
 
 		\OCP\Util::addScript('files', 'detailfileinfoview');
 		\OCP\Util::addScript('files', 'sidebarpreviewmanager');
+		\OCP\Util::addScript('files', 'sidebarpreviewtext');
 		\OCP\Util::addScript('files', 'detailtabview');
 		\OCP\Util::addScript('files', 'mainfileinfodetailview');
 		\OCP\Util::addScript('files', 'detailsview');

From e7039425fb64e737e068beda7cb426e3f00dde0b Mon Sep 17 00:00:00 2001
From: Morris Jobke 
Date: Mon, 4 Jul 2016 15:38:16 +0200
Subject: [PATCH 73/81] adjust padding of text preview

---
 apps/files/css/detailsView.css | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
index a49b37e6aaba4..2ec16993ef53a 100644
--- a/apps/files/css/detailsView.css
+++ b/apps/files/css/detailsView.css
@@ -67,11 +67,12 @@
 	background-size: contain;
 }
 
-#app-sidebar .text {
+#app-sidebar .large.text {
 	overflow-y: scroll;
 	overflow-x: hidden;
-	padding-left: 5px;
+	padding-top: 15px;
 	font-size: 80%;
+	margin-left: 0;
 }
 
 #app-sidebar .thumbnail {

From 25d535914ed0fd2eb2570febbfee9e459d7b660e Mon Sep 17 00:00:00 2001
From: Morris Jobke 
Date: Mon, 4 Jul 2016 17:38:26 +0200
Subject: [PATCH 74/81] for text use max-height to trim whitespace

---
 apps/files/js/sidebarpreviewtext.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/files/js/sidebarpreviewtext.js b/apps/files/js/sidebarpreviewtext.js
index de264ed1e56e6..5af17bd55519e 100644
--- a/apps/files/js/sidebarpreviewtext.js
+++ b/apps/files/js/sidebarpreviewtext.js
@@ -29,7 +29,7 @@
 				var $textPreview = $('
').text(content);
 				$thumbnailDiv.children('.stretcher').remove();
 				$thumbnailDiv.append($textPreview);
-				$thumbnailContainer.height(previewHeight);
+				$thumbnailContainer.css("max-height", previewHeight);
 			}, function () {
 				fallback();
 			});

From f173ced67c4624dbb1e8188209abead18310dd08 Mon Sep 17 00:00:00 2001
From: Thomas Pulzer 
Date: Mon, 4 Jul 2016 22:57:10 +0200
Subject: [PATCH 75/81] Changed the creation of the update notification link to
 generate the js object from concated string.

---
 apps/updatenotification/js/notification.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/updatenotification/js/notification.js b/apps/updatenotification/js/notification.js
index 810b9c168afb7..d5463174e4ca4 100644
--- a/apps/updatenotification/js/notification.js
+++ b/apps/updatenotification/js/notification.js
@@ -18,7 +18,7 @@ $(document).ready(function(){
 		version = oc_updateState.updateVersion,
 		docLink = oc_updateState.updateLink,
 		text = t('core', '{version} is available. Get more information on how to update.', {version: version}),
-		element = $('').attr('href', docLink).attr('target','_blank').text(text);
+		element = $(''+text+'');
 
 	OC.Notification.showTemporary(
 		element,

From 601c5b85c4641ede38eb65bc6eb9b95fb721d90d Mon Sep 17 00:00:00 2001
From: Thomas Pulzer 
Date: Tue, 5 Jul 2016 06:59:11 +0200
Subject: [PATCH 76/81] Added escaping html code when building link to
 documentation.

---
 apps/updatenotification/js/notification.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/updatenotification/js/notification.js b/apps/updatenotification/js/notification.js
index d5463174e4ca4..913a59e042cb5 100644
--- a/apps/updatenotification/js/notification.js
+++ b/apps/updatenotification/js/notification.js
@@ -18,7 +18,7 @@ $(document).ready(function(){
 		version = oc_updateState.updateVersion,
 		docLink = oc_updateState.updateLink,
 		text = t('core', '{version} is available. Get more information on how to update.', {version: version}),
-		element = $(''+text+'');
+		element = $(''+escapeHTML(text)+'');
 
 	OC.Notification.showTemporary(
 		element,

From 3af6b73a070cfabfadb84c28e39df8587b11d208 Mon Sep 17 00:00:00 2001
From: Bugsbane 
Date: Tue, 5 Jul 2016 06:16:25 -0400
Subject: [PATCH 77/81] Update system tags icon

Change system tags icon from a magnifying glass to a newly created tag icon. Updates both the png and it's original source SVG.
---
 apps/systemtags/img/tag.png | Bin 293 -> 420 bytes
 apps/systemtags/img/tag.svg |  82 ++++++++++++++++++++++++++++++++++--
 2 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/apps/systemtags/img/tag.png b/apps/systemtags/img/tag.png
index 5f4767a6f461956689bc15b231cafe91e5690481..694a8cf17adff96372621736491371aa7fcf92d7 100644
GIT binary patch
delta 405
zcmV;G0c!rG0;B_w8Gi-<001BJ|6u?C00eVFNmK|32nc)#WQYI&010qNS#tmY4c7nw
z4c7reD4Tcy000?uMObuGZ)S9NVRB^vcXxL#X>MzCV_|S*E^l&Yo9;Xs0003YNklgRC3fcW@y&L#~i4vVU;nTH;C&FVIbT1s7f*
z6)P5kOc@s@Wm?RKZ}SG`z2ER2Bd{U}0_FSu0H7#}&n(Nfbc6s1!*C4@>2wHOHH=y#o;U<-ByDM4XszdfQB4&sJ6UM0
zXK9*#fwjb*$X;_NaDc2`*S(J8c+=JMulNCESbmEVTn?#r00000NkvXXu0mjf?YN~B

literal 293
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}NPtg>>;M1%flTUx4SfrRfhNk7
z1o;Ish)c=HDyV4a7}|Jv`bT8s<`ou~mRD3&*VZ>wM9eS(s!Q>7aSW-rmFs_9s6m0}
zG8dnSj0VTg|NleY$GCo;l)Y=x8~#HP*++s`cgP0b{VQQIk?-Ry!wc-0GlDlPXyz~z
zJyx>RyKm9Md`9)SV{O~!JyiWXTR*~k*#zem6>9zSmQM-(*t?IhO`lEmw`2NGkWW2b
L{an^LB{Ts5S9eS3

diff --git a/apps/systemtags/img/tag.svg b/apps/systemtags/img/tag.svg
index 6024607dd0aaa..6ebba7ac23f08 100644
--- a/apps/systemtags/img/tag.svg
+++ b/apps/systemtags/img/tag.svg
@@ -1,5 +1,81 @@
 
-
- 
- 
+
+  
+    
+      
+        image/svg+xml
+        
+      
+    
+  
+  
+  
+    
+    
+    
+    
+  
+  
+  
 

From d596265a7a355a2afef42f176770c72848f79b89 Mon Sep 17 00:00:00 2001
From: Bugsbane 
Date: Tue, 5 Jul 2016 06:18:02 -0400
Subject: [PATCH 78/81] Clean the svg with inkscapes clean document function


From c86064b4e5bdb08f13b92ecc6d4207a4ab914db5 Mon Sep 17 00:00:00 2001
From: Bugsbane 
Date: Tue, 5 Jul 2016 06:52:10 -0400
Subject: [PATCH 79/81] Replace tag svg with optimized version

Replace the system tags tag icon svg with a version that has been optimized by the optimization script (running scour)
---
 apps/systemtags/img/tag.svg | 82 ++-----------------------------------
 1 file changed, 3 insertions(+), 79 deletions(-)

diff --git a/apps/systemtags/img/tag.svg b/apps/systemtags/img/tag.svg
index 6ebba7ac23f08..bf4688c92283d 100644
--- a/apps/systemtags/img/tag.svg
+++ b/apps/systemtags/img/tag.svg
@@ -1,81 +1,5 @@
 
-
-  
-    
-      
-        image/svg+xml
-        
-      
-    
-  
-  
-  
-    
-    
-    
-    
-  
-  
-  
+
+ 
+ 
 

From 8e4849efd2cd74b9e219454f51a7c1a0dde83bcb Mon Sep 17 00:00:00 2001
From: Bugsbane 
Date: Thu, 7 Jul 2016 07:01:44 -0400
Subject: [PATCH 80/81] Added class for "Recent" sidebar icon

Added the new css class that pulls in the "recent" icon in the sidebar for @Icewind's new "recent files" file listing in https://github.com/nextcloud/server/pull/292#issuecomment-231042766
---
 apps/files/css/files.css | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index ebb44f3070c93..47bb44c0fd399 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -86,6 +86,9 @@
 }
 
 /* icons for sidebar */
+.nav-icon-recent {
+	background-image: url('../img/recent.svg');
+}
 .nav-icon-files {
 	background-image: url('../img/folder.svg');
 }

From e37f07ae5f989fa45a8d638b3829ab2a9faaae57 Mon Sep 17 00:00:00 2001
From: Bugsbane 
Date: Thu, 7 Jul 2016 18:36:56 -0400
Subject: [PATCH 81/81] Add the recent files icon

Add the clock icon (svg and png) discussed with Jan and Icewind for the "recent files" view.
---
 apps/files/img/recent.png | Bin 0 -> 679 bytes
 apps/files/img/recent.svg |   7 +++++++
 2 files changed, 7 insertions(+)
 create mode 100644 apps/files/img/recent.png
 create mode 100644 apps/files/img/recent.svg

diff --git a/apps/files/img/recent.png b/apps/files/img/recent.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e0f7e1a537c131be52ba86fffbb2aea3d6998b5
GIT binary patch
literal 679
zcmV;Y0$BZtP)KNrBbP!3B$0es#gIE^nt}rr?ZhHNqB7FPreE4i^%16yWJcb8rsRS
zY%j~QVQcNTG))_-ItlEn>eRu(!83rMUayb)vb!R3yWMVY19ZFH3E;FbX0oW?TDzsH
zGe8emXti2nK@bFUzLGbE7{C~F$-@ifCU}!oz~p&87XZ_~)9YoTs{Yr&$9um{2f$f?
zJkNg&7|eKhZBSjQRCYZ)cl=z{YE{Z45eYp!)o3&xmUCH_6Vr6r
zFAm-}P1B!gn%=3^Y9jzkOG^{LJdhh>-U>jY(Rc|gax^3}*4nK>qeASQ`v?rH>I-Xa
zd;%bfqE@HVIj^cyBJw?s<5gqKdKiW~hlht6hT*t#Zq_+B4}`#%TCMg7N}nl7lF*Om
z0$~1E0gwZ)q9}S?d?p!Wv|6pPJkRGi8n6*Sf#1LlQn{~yPH;2xqMou~i+
N002ovPDHLkV1k#`B!K_`

literal 0
HcmV?d00001

diff --git a/apps/files/img/recent.svg b/apps/files/img/recent.svg
new file mode 100644
index 0000000000000..32cfb109afbeb
--- /dev/null
+++ b/apps/files/img/recent.svg
@@ -0,0 +1,7 @@
+
+
+ 
+ 
+ 
+ 
+