From 3645308d0bd7742a84323f92be842d9fef84bc0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hler?= Date: Tue, 28 Jul 2015 10:31:49 +0200 Subject: [PATCH 001/344] Add possibility for alternative logins to force redirection of login page --- lib/private/util.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/private/util.php b/lib/private/util.php index 39d64952dc6..4f988abfe1b 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -901,6 +901,14 @@ class OC_Util { $parameters['alt_login'] = OC_App::getAlternativeLogIns(); $parameters['rememberLoginAllowed'] = self::rememberLoginAllowed(); + foreach($parameters['alt_login'] as $params) + { + if(isset($params['forceredirect']) && ($params['forceredirect'] === true)) + { + \OCP\Response::redirect($params['href']); + exit(); + } + } OC_Template::printGuestPage("", "login", $parameters); } -- GitLab From 3a0d42ecf3da8cd7c0123131c096dd7fd4d4b4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hler?= Date: Tue, 28 Jul 2015 13:00:18 +0200 Subject: [PATCH 002/344] Add hook 'pre_displayLoginPage' --- lib/private/util.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/private/util.php b/lib/private/util.php index 4f988abfe1b..c3a15a402cc 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -901,14 +901,7 @@ class OC_Util { $parameters['alt_login'] = OC_App::getAlternativeLogIns(); $parameters['rememberLoginAllowed'] = self::rememberLoginAllowed(); - foreach($parameters['alt_login'] as $params) - { - if(isset($params['forceredirect']) && ($params['forceredirect'] === true)) - { - \OCP\Response::redirect($params['href']); - exit(); - } - } + \OC_Hook::emit('OC_Util', 'pre_displayLoginPage', array('parameters' => $parameters)); OC_Template::printGuestPage("", "login", $parameters); } -- GitLab From 2577a624c0b1ce157a2ed52820dfa6a2db1662d4 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 11 Feb 2015 01:06:07 +0100 Subject: [PATCH 003/344] [files_external] swift tests --- apps/files_external/tests/backends/swift.php | 9 ++- .../tests/env/start-swift-morrisjobke.sh | 66 +++++++++++++++++++ .../tests/env/stop-swift-morrisjobke.sh | 36 ++++++++++ 3 files changed, 106 insertions(+), 5 deletions(-) create mode 100755 apps/files_external/tests/env/start-swift-morrisjobke.sh create mode 100755 apps/files_external/tests/env/stop-swift-morrisjobke.sh diff --git a/apps/files_external/tests/backends/swift.php b/apps/files_external/tests/backends/swift.php index 2e6670f84f8..4ca2d1db7bd 100644 --- a/apps/files_external/tests/backends/swift.php +++ b/apps/files_external/tests/backends/swift.php @@ -32,18 +32,17 @@ class Swift extends Storage { protected function setUp() { parent::setUp(); - $this->config = include('files_external/tests/config.php'); - if (!is_array($this->config) or !isset($this->config['swift']) - or !$this->config['swift']['run']) { + $this->config = include('files_external/tests/config.swift.php'); + if (!is_array($this->config) or !$this->config['run']) { $this->markTestSkipped('OpenStack Object Storage backend not configured'); } - $this->instance = new \OC\Files\Storage\Swift($this->config['swift']); + $this->instance = new \OC\Files\Storage\Swift($this->config); } protected function tearDown() { if ($this->instance) { $connection = $this->instance->getConnection(); - $container = $connection->getContainer($this->config['swift']['bucket']); + $container = $connection->getContainer($this->config['bucket']); $objects = $container->objectList(); while($object = $objects->next()) { diff --git a/apps/files_external/tests/env/start-swift-morrisjobke.sh b/apps/files_external/tests/env/start-swift-morrisjobke.sh new file mode 100755 index 00000000000..d6cd0d22e9d --- /dev/null +++ b/apps/files_external/tests/env/start-swift-morrisjobke.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# +# ownCloud +# +# This script start a docker container to test the files_external tests +# against. It will also change the files_external config to use the docker +# container as testing environment. This is reverted in the stop step.W +# +# Set environment variable DEBUG to print config file +# +# @author Morris Jobke +# @copyright 2015 Morris Jobke +# + +if ! command -v docker >/dev/null 2>&1; then + echo "No docker executable found - skipped docker setup" + exit 0; +fi + +echo "Docker executable found - setup docker" + +echo "Fetch recent morrisjobke/docker-swift-onlyone docker image" +docker pull morrisjobke/docker-swift-onlyone + +# retrieve current folder to place the config in the parent folder +thisFolder=`echo $0 | replace "env/start-swift-morrisjobke.sh" ""` + +if [ -z "$thisFolder" ]; then + thisFolder="." +fi; + +container=`docker run -d -e SWIFT_SET_PASSWORDS=true morrisjobke/docker-swift-onlyone` + +host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` + + +echo "swift container: $container" + +# put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) +echo $container >> $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift + +# TODO find a way to determine the successful initialization inside the docker container +echo "Waiting 15 seconds for swift initialization ... " +sleep 15 + +user=test:tester +password=`docker logs $container | grep "user_test_tester " | cut -d " " -f3` + +cat > $thisFolder/config.swift.php <true, + 'url'=>'http://$host:8080/auth/v1.0', + 'user'=>'$user', + 'key'=>'$password', + 'bucket'=>'swift', + 'region' => 'DFW', +); + +DELIM + +if [ -n "$DEBUG" ]; then + cat $thisFolder/config.swift.php + cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift +fi diff --git a/apps/files_external/tests/env/stop-swift-morrisjobke.sh b/apps/files_external/tests/env/stop-swift-morrisjobke.sh new file mode 100755 index 00000000000..f1660e65854 --- /dev/null +++ b/apps/files_external/tests/env/stop-swift-morrisjobke.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# ownCloud +# +# This script stops the docker container the files_external tests were run +# against. It will also revert the config changes done in start step. +# +# @author Morris Jobke +# @copyright 2015 Morris Jobke +# + +if ! command -v docker >/dev/null 2>&1; then + echo "No docker executable found - skipped docker stop" + exit 0; +fi + +echo "Docker executable found - stop and remove docker containers" + +# retrieve current folder to remove the config from the parent folder +thisFolder=`echo $0 | replace "env/stop-swift-morrisjobke.sh" ""` + +if [ -z "$thisFolder" ]; then + thisFolder="." +fi; + +# stopping and removing docker containers +for container in `cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift`; do + echo "Stopping and removing docker container $container" + # kills running container and removes it + docker rm -f $container +done; + +# cleanup +rm $thisFolder/config.swift.php +rm $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift + -- GitLab From 0de9819da378590fee73c805b5e52661452eb141 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Wed, 9 Sep 2015 22:06:41 +0100 Subject: [PATCH 004/344] Replace Swift Docker test with Ceph image --- ...ift-morrisjobke.sh => start-swift-ceph.sh} | 50 ++++++++++++------- ...wift-morrisjobke.sh => stop-swift-ceph.sh} | 10 ++-- 2 files changed, 38 insertions(+), 22 deletions(-) rename apps/files_external/tests/env/{start-swift-morrisjobke.sh => start-swift-ceph.sh} (53%) rename apps/files_external/tests/env/{stop-swift-morrisjobke.sh => stop-swift-ceph.sh} (72%) diff --git a/apps/files_external/tests/env/start-swift-morrisjobke.sh b/apps/files_external/tests/env/start-swift-ceph.sh similarity index 53% rename from apps/files_external/tests/env/start-swift-morrisjobke.sh rename to apps/files_external/tests/env/start-swift-ceph.sh index d6cd0d22e9d..c2e7d4c1ae1 100755 --- a/apps/files_external/tests/env/start-swift-morrisjobke.sh +++ b/apps/files_external/tests/env/start-swift-ceph.sh @@ -9,8 +9,8 @@ # Set environment variable DEBUG to print config file # # @author Morris Jobke -# @copyright 2015 Morris Jobke -# +# @author Robin McCorkell +# @copyright 2015 ownCloud if ! command -v docker >/dev/null 2>&1; then echo "No docker executable found - skipped docker setup" @@ -19,48 +19,64 @@ fi echo "Docker executable found - setup docker" -echo "Fetch recent morrisjobke/docker-swift-onlyone docker image" -docker pull morrisjobke/docker-swift-onlyone +docker_image=xenopathic/ceph-keystone + +echo "Fetch recent ${docker_image} docker image" +docker pull ${docker_image} # retrieve current folder to place the config in the parent folder -thisFolder=`echo $0 | replace "env/start-swift-morrisjobke.sh" ""` +thisFolder=`echo $0 | replace "env/start-swift-ceph.sh" ""` if [ -z "$thisFolder" ]; then thisFolder="." fi; -container=`docker run -d -e SWIFT_SET_PASSWORDS=true morrisjobke/docker-swift-onlyone` +port=5001 + +user=test +pass=testing +tenant=testenant +region=testregion +service=testceph + +container=`docker run -d \ + -e KEYSTONE_PUBLIC_PORT=${port} \ + -e KEYSTONE_ADMIN_USER=${user} \ + -e KEYSTONE_ADMIN_PASS=${pass} \ + -e KEYSTONE_ADMIN_TENANT=${tenant} \ + -e KEYSTONE_ENDPOINT_REGION=${region} \ + -e KEYSTONE_SERVICE=${service} \ + ${docker_image}` host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` -echo "swift container: $container" +echo "${docker_image} container: $container" # put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) -echo $container >> $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift +echo $container >> $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.swift # TODO find a way to determine the successful initialization inside the docker container -echo "Waiting 15 seconds for swift initialization ... " -sleep 15 - -user=test:tester -password=`docker logs $container | grep "user_test_tester " | cut -d " " -f3` +echo "Waiting 20 seconds for ceph initialization ... " +sleep 20 cat > $thisFolder/config.swift.php <true, - 'url'=>'http://$host:8080/auth/v1.0', + 'url'=>'http://$host:$port/v2.0', 'user'=>'$user', - 'key'=>'$password', + 'tenant'=>'$tenant', + 'password'=>'$pass', + 'service_name'=>'$service', 'bucket'=>'swift', - 'region' => 'DFW', + 'region' => '$region', ); DELIM if [ -n "$DEBUG" ]; then cat $thisFolder/config.swift.php - cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift + cat $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.swift fi diff --git a/apps/files_external/tests/env/stop-swift-morrisjobke.sh b/apps/files_external/tests/env/stop-swift-ceph.sh similarity index 72% rename from apps/files_external/tests/env/stop-swift-morrisjobke.sh rename to apps/files_external/tests/env/stop-swift-ceph.sh index f1660e65854..edac1389a78 100755 --- a/apps/files_external/tests/env/stop-swift-morrisjobke.sh +++ b/apps/files_external/tests/env/stop-swift-ceph.sh @@ -6,8 +6,8 @@ # against. It will also revert the config changes done in start step. # # @author Morris Jobke -# @copyright 2015 Morris Jobke -# +# @author Robin McCorkell +# @copyright 2015 ownCloud if ! command -v docker >/dev/null 2>&1; then echo "No docker executable found - skipped docker stop" @@ -17,14 +17,14 @@ fi echo "Docker executable found - stop and remove docker containers" # retrieve current folder to remove the config from the parent folder -thisFolder=`echo $0 | replace "env/stop-swift-morrisjobke.sh" ""` +thisFolder=`echo $0 | replace "env/stop-swift-ceph.sh" ""` if [ -z "$thisFolder" ]; then thisFolder="." fi; # stopping and removing docker containers -for container in `cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift`; do +for container in `cat $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.swift`; do echo "Stopping and removing docker container $container" # kills running container and removes it docker rm -f $container @@ -32,5 +32,5 @@ done; # cleanup rm $thisFolder/config.swift.php -rm $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.swift +rm $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.swift -- GitLab From 70f4e9413fc4b7f676ecdb6b437751182a07dc56 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Wed, 23 Sep 2015 20:31:22 +0100 Subject: [PATCH 005/344] Make Swift test robust if container didn't exist --- apps/files_external/tests/backends/swift.php | 22 ++++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/files_external/tests/backends/swift.php b/apps/files_external/tests/backends/swift.php index 4ca2d1db7bd..83b27e6e82e 100644 --- a/apps/files_external/tests/backends/swift.php +++ b/apps/files_external/tests/backends/swift.php @@ -41,16 +41,20 @@ class Swift extends Storage { protected function tearDown() { if ($this->instance) { - $connection = $this->instance->getConnection(); - $container = $connection->getContainer($this->config['bucket']); - - $objects = $container->objectList(); - while($object = $objects->next()) { - $object->setName(str_replace('#','%23',$object->getName())); - $object->delete(); + try { + $connection = $this->instance->getConnection(); + $container = $connection->getContainer($this->config['bucket']); + + $objects = $container->objectList(); + while($object = $objects->next()) { + $object->setName(str_replace('#','%23',$object->getName())); + $object->delete(); + } + + $container->delete(); + } catch (\Guzzle\Http\Exception\ClientErrorResponseException $e) { + // container didn't exist, so we don't need to delete it } - - $container->delete(); } parent::tearDown(); -- GitLab From 8467dbfa91921ccb0262161360edbf339f6b7daa Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Wed, 23 Sep 2015 22:33:39 +0100 Subject: [PATCH 006/344] Detect Docker initialization properly Use netcat to check when the port opens, rather than an arbitrary timeout. Hard limit of 60 seconds in case something breaks --- .../tests/env/start-amazons3-ceph.sh | 18 ++++++++++--- .../tests/env/start-ftp-morrisjobke.sh | 19 +++++++++++--- .../tests/env/start-sftp-atmoz.sh | 20 +++++++++++--- .../tests/env/start-smb-silvershell.sh | 19 +++++++++++--- .../tests/env/start-swift-ceph.sh | 18 ++++++++++--- .../tests/env/start-webdav-ownCloud.sh | 26 +++++++++++++------ 6 files changed, 96 insertions(+), 24 deletions(-) diff --git a/apps/files_external/tests/env/start-amazons3-ceph.sh b/apps/files_external/tests/env/start-amazons3-ceph.sh index ad0fedba989..f2beb0bd714 100755 --- a/apps/files_external/tests/env/start-amazons3-ceph.sh +++ b/apps/files_external/tests/env/start-amazons3-ceph.sh @@ -49,9 +49,21 @@ echo "${docker_image} container: $container" # put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) echo $container >> $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.amazons3 -# TODO find a way to determine the successful initialization inside the docker container -echo "Waiting 20 seconds for ceph initialization ... " -sleep 20 +echo -n "Waiting for ceph initialization" +starttime=$(date +%s) +# support for GNU netcat and BSD netcat +while ! (nc -c -w 1 ${host} ${port} &/dev/null \ + || nc -w 1 ${host} ${port} &/dev/null); do + sleep 1 + echo -n '.' + if (( $(date +%s) > starttime + 60 )); then + echo + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 + fi +done +echo +sleep 1 echo "Create ceph user" docker exec $container radosgw-admin user create \ diff --git a/apps/files_external/tests/env/start-ftp-morrisjobke.sh b/apps/files_external/tests/env/start-ftp-morrisjobke.sh index 14112d7f803..35e3eafb839 100755 --- a/apps/files_external/tests/env/start-ftp-morrisjobke.sh +++ b/apps/files_external/tests/env/start-ftp-morrisjobke.sh @@ -54,12 +54,25 @@ echo "ftp container: $container" # put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) echo $container >> $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.ftp +echo -n "Waiting for ftp initialization" +starttime=$(date +%s) +# support for GNU netcat and BSD netcat +while ! (nc -c -w 1 ${host} 21 &/dev/null \ + || nc -w 1 ${host} 21 &/dev/null); do + sleep 1 + echo -n '.' + if (( $(date +%s) > starttime + 60 )); then + echo + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 + fi +done +echo +sleep 1 + if [ -n "$DEBUG" ]; then cat $thisFolder/config.ftp.php cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.ftp fi -# TODO find a way to determine the successful initialization inside the docker container -echo "Waiting 5 seconds for ftp initialization ... " -sleep 5 diff --git a/apps/files_external/tests/env/start-sftp-atmoz.sh b/apps/files_external/tests/env/start-sftp-atmoz.sh index 91eb5747c54..c4ef81b8357 100755 --- a/apps/files_external/tests/env/start-sftp-atmoz.sh +++ b/apps/files_external/tests/env/start-sftp-atmoz.sh @@ -54,15 +54,27 @@ echo "sftp container: $container" # put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) echo $container >> $thisFolder/dockerContainerAtmoz.$EXECUTOR_NUMBER.sftp +echo -n "Waiting for sftp initialization" +starttime=$(date +%s) +# support for GNU netcat and BSD netcat +while ! (nc -c -w 1 ${host} 22 &/dev/null \ + || nc -w 1 ${host} 22 &/dev/null); do + sleep 1 + echo -n '.' + if (( $(date +%s) > starttime + 60 )); then + echo + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 + fi +done +echo +sleep 1 + if [ -n "$DEBUG" ]; then cat $thisFolder/config.sftp.php cat $thisFolder/dockerContainerAtmoz.$EXECUTOR_NUMBER.sftp fi -# TODO find a way to determine the successful initialization inside the docker container -echo "Waiting 5 seconds for sftp initialization ... " -sleep 5 - # create folder "upload" with correct permissions docker exec $container bash -c "mkdir /home/$user/upload && chown $user:users /home/$user/upload" diff --git a/apps/files_external/tests/env/start-smb-silvershell.sh b/apps/files_external/tests/env/start-smb-silvershell.sh index c45807cc4c8..e2aa025c711 100755 --- a/apps/files_external/tests/env/start-smb-silvershell.sh +++ b/apps/files_external/tests/env/start-smb-silvershell.sh @@ -52,12 +52,25 @@ echo "samba container: $container" # put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) echo $container >> $thisFolder/dockerContainerSilvershell.$EXECUTOR_NUMBER.smb +echo -n "Waiting for samba initialization" +starttime=$(date +%s) +# support for GNU netcat and BSD netcat +while ! (nc -c -w 1 ${host} 445 &/dev/null \ + || nc -w 1 ${host} 445 &/dev/null); do + sleep 1 + echo -n '.' + if (( $(date +%s) > starttime + 60 )); then + echo + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 + fi +done +echo +sleep 1 + if [ -n "$DEBUG" ]; then cat $thisFolder/config.smb.php cat $thisFolder/dockerContainerSilvershell.$EXECUTOR_NUMBER.smb fi -# TODO find a way to determine the successful initialization inside the docker container -echo "Waiting 5 seconds for smbd initialization ... " -sleep 5 diff --git a/apps/files_external/tests/env/start-swift-ceph.sh b/apps/files_external/tests/env/start-swift-ceph.sh index c2e7d4c1ae1..a8305eee5a2 100755 --- a/apps/files_external/tests/env/start-swift-ceph.sh +++ b/apps/files_external/tests/env/start-swift-ceph.sh @@ -56,9 +56,21 @@ echo "${docker_image} container: $container" # put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) echo $container >> $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.swift -# TODO find a way to determine the successful initialization inside the docker container -echo "Waiting 20 seconds for ceph initialization ... " -sleep 20 +echo -n "Waiting for ceph initialization" +starttime=$(date +%s) +# support for GNU netcat and BSD netcat +while ! (nc -c -w 1 ${host} 80 &/dev/null \ + || nc -w 1 ${host} 80 &/dev/null); do + sleep 1 + echo -n '.' + if (( $(date +%s) > starttime + 60 )); then + echo + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 + fi +done +echo +sleep 1 cat > $thisFolder/config.swift.php <&/dev/null \ + || nc -w 1 ${host} 80 &/dev/null); do + sleep 1 + echo -n '.' + if (( $(date +%s) > starttime + 60 )); then + echo + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 + fi +done +echo +sleep 1 cat > $thisFolder/config.webdav.php <true, - 'host'=>'localhost:$port/owncloud/remote.php/webdav/', + 'host'=>'${host}:80/owncloud/remote.php/webdav/', 'user'=>'test', 'password'=>'test', 'root'=>'', -- GitLab From ad028c555d8517091b60bf9aff97fa0ab22a93ac Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Wed, 23 Sep 2015 23:18:16 +0100 Subject: [PATCH 007/344] Don't attempt to run tests unless start file is successful --- .../tests/env/start-smb-windows.sh | 6 ++ autotest-external.sh | 81 +++++++++---------- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/apps/files_external/tests/env/start-smb-windows.sh b/apps/files_external/tests/env/start-smb-windows.sh index 2143d7e7499..6779cdb2d56 100755 --- a/apps/files_external/tests/env/start-smb-windows.sh +++ b/apps/files_external/tests/env/start-smb-windows.sh @@ -19,6 +19,12 @@ user=smb-test password=!owncloud123 host=WIN-9GTFAS08C15 +if ! (nc -c -w 1 ${host} 445 &/dev/null \ + || nc -w 1 ${host} 445 &/dev/null); then + echo "[ERROR] Server not reachable" >&2 + exit 1 +fi + cat > $thisFolder/config.smb.php < Date: Thu, 24 Sep 2015 14:33:54 +0100 Subject: [PATCH 008/344] Skip Swift stat test --- apps/files_external/tests/backends/swift.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/files_external/tests/backends/swift.php b/apps/files_external/tests/backends/swift.php index 83b27e6e82e..07ee36043b1 100644 --- a/apps/files_external/tests/backends/swift.php +++ b/apps/files_external/tests/backends/swift.php @@ -59,4 +59,8 @@ class Swift extends Storage { parent::tearDown(); } + + public function testStat() { + $this->markTestSkipped('Swift doesn\'t update the parents folder mtime'); + } } -- GitLab From 9234b8c194eeca8ad27a12cfbd7aabf9920c9ca6 Mon Sep 17 00:00:00 2001 From: Hendrik Leppelsack Date: Thu, 29 Oct 2015 13:23:57 +0100 Subject: [PATCH 009/344] make new checkbox style accessible for screenreaders --- core/css/styles.css | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/css/styles.css b/core/css/styles.css index abefd2748b2..060576cb2c0 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -164,11 +164,12 @@ textarea:hover, textarea:focus, textarea:active { /* ie8 doesn't support :checked */ html:not(.ie8) input[type="checkbox"].checkbox { - margin:0; - padding:0; - height:auto; - width:auto; - display: none; + position: absolute; + left:-10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; } html:not(.ie8) input[type="checkbox"].checkbox + label:before { -- GitLab From 46a8eab772f82923cab6e158f7b71df5415081d9 Mon Sep 17 00:00:00 2001 From: Mario Kolling Date: Thu, 16 Jul 2015 17:17:57 -0300 Subject: [PATCH 010/344] Fix RHDS ldap paged search, Issue #17173 Change-Id: Ic804ea95401a9b49cb2b0866af722aa0d3ee58c5 --- apps/user_ldap/lib/access.php | 106 +++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index d4f4eaddcb3..614afca462d 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -865,14 +865,13 @@ class Access extends LDAPUtility implements user\IUserTools { * @param bool $pagedSearchOK whether a paged search has been executed * @param bool $skipHandling required for paged search when cookies to * prior results need to be gained - * @return array|false array with the search result as first value and pagedSearchOK as - * second | false if not successful + * @return bool cookie validity, true if we have more pages, false otherwise. */ private function processPagedSearchStatus($sr, $filter, $base, $iFoundItems, $limit, $offset, $pagedSearchOK, $skipHandling) { + $cookie = null; if($pagedSearchOK) { $cr = $this->connection->getConnectionResource(); foreach($sr as $key => $res) { - $cookie = null; if($this->ldap->controlPagedResultResponse($cr, $res, $cookie)) { $this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie); } @@ -893,6 +892,12 @@ class Access extends LDAPUtility implements user\IUserTools { \OCP\Util::writeLog('user_ldap', 'Paged search was not available', \OCP\Util::INFO); } } + /* ++ Fixing RHDS searches with pages with zero results ++ + * Return cookie status. If we don't have more pages, with RHDS + * cookie is null, with openldap cookie is an empty string and + * to 386ds '0' is a valid cookie. Even if $iFoundItems == 0 + */ + return !empty($cookie) || $cookie === '0'; } /** @@ -921,7 +926,6 @@ class Access extends LDAPUtility implements user\IUserTools { $this->connection->getConnectionResource(); do { - $continue = false; $search = $this->executeSearch($filter, $base, $attr, $limitPerPage, $offset); if($search === false) { @@ -929,12 +933,20 @@ class Access extends LDAPUtility implements user\IUserTools { } list($sr, $pagedSearchOK) = $search; - $count = $this->countEntriesInSearchResults($sr, $limitPerPage, $continue); + /* ++ Fixing RHDS searches with pages with zero results ++ + * countEntriesInSearchResults() method signature changed + * by removing $limit and &$hasHitLimit parameters + */ + $count = $this->countEntriesInSearchResults($sr); $counter += $count; - $this->processPagedSearchStatus($sr, $filter, $base, $count, $limitPerPage, + $hasMorePages = $this->processPagedSearchStatus($sr, $filter, $base, $count, $limitPerPage, $offset, $pagedSearchOK, $skipHandling); $offset += $limitPerPage; + /* ++ Fixing RHDS searches with pages with zero results ++ + * Continue now depends on $hasMorePages value + */ + $continue = $pagedSearchOK && $hasMorePages; } while($continue && (is_null($limit) || $limit <= 0 || $limit > $counter)); return $counter; @@ -942,20 +954,15 @@ class Access extends LDAPUtility implements user\IUserTools { /** * @param array $searchResults - * @param int $limit - * @param bool $hasHitLimit * @return int */ - private function countEntriesInSearchResults($searchResults, $limit, &$hasHitLimit) { + private function countEntriesInSearchResults($searchResults) { $cr = $this->connection->getConnectionResource(); $counter = 0; foreach($searchResults as $res) { $count = intval($this->ldap->countEntries($cr, $res)); $counter += $count; - if($count > 0 && $count === $limit) { - $hasHitLimit = true; - } } return $counter; @@ -976,38 +983,53 @@ class Access extends LDAPUtility implements user\IUserTools { //otherwise search will fail $limit = null; } - $search = $this->executeSearch($filter, $base, $attr, $limit, $offset); - if($search === false) { - return array(); - } - list($sr, $pagedSearchOK) = $search; - $cr = $this->connection->getConnectionResource(); - if($skipHandling) { - //i.e. result do not need to be fetched, we just need the cookie - //thus pass 1 or any other value as $iFoundItems because it is not - //used - $this->processPagedSearchStatus($sr, $filter, $base, 1, $limit, - $offset, $pagedSearchOK, - $skipHandling); - return array(); - } + /* ++ Fixing RHDS searches with pages with zero results ++ + * As we can have pages with zero results and/or pages with less + * than $limit results but with a still valid server 'cookie', + * loops through until we get $continue equals true and + * $findings['count'] < $limit + */ + $findings = array(); + $savedoffset = $offset; + do { + $continue = false; + $search = $this->executeSearch($filter, $base, $attr, $limit, $offset); + if($search === false) { + return array(); + } + list($sr, $pagedSearchOK) = $search; + $cr = $this->connection->getConnectionResource(); - // Do the server-side sorting - foreach(array_reverse($attr) as $sortAttr){ - foreach($sr as $searchResource) { - $this->ldap->sort($cr, $searchResource, $sortAttr); + if($skipHandling) { + //i.e. result do not need to be fetched, we just need the cookie + //thus pass 1 or any other value as $iFoundItems because it is not + //used + $this->processPagedSearchStatus($sr, $filter, $base, 1, $limit, + $offset, $pagedSearchOK, + $skipHandling); + return array(); } - } - $findings = array(); - foreach($sr as $res) { - $findings = array_merge($findings, $this->ldap->getEntries($cr , $res )); - } + // Do the server-side sorting + foreach(array_reverse($attr) as $sortAttr){ + foreach($sr as $searchResource) { + $this->ldap->sort($cr, $searchResource, $sortAttr); + } + } + + + foreach($sr as $res) { + $findings = array_merge($findings, $this->ldap->getEntries($cr , $res )); + } - $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'], - $limit, $offset, $pagedSearchOK, + $continue = $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'], + $limit, $offset, $pagedSearchOK, $skipHandling); + $offset += $limit; + } while ($continue && $pagedSearchOK && $findings['count'] < $limit); + // reseting offset + $offset = $savedoffset; // if we're here, probably no connection resource is returned. // to make ownCloud behave nicely, we simply give back an empty array. @@ -1595,7 +1617,13 @@ class Access extends LDAPUtility implements user\IUserTools { } } - } else if($this->connection->hasPagedResultSupport && $limit === 0) { + /* ++ Fixing RHDS searches with pages with zero results ++ + * We coudn't get paged searches working with our RHDS for login ($limit = 0), + * due to pages with zero results. + * So we added "&& !empty($this->lastCookie)" to this test to ignore pagination + * if we don't have a previous paged search. + */ + } else if($this->connection->hasPagedResultSupport && $limit === 0 && !empty($this->lastCookie)) { // a search without limit was requested. However, if we do use // Paged Search once, we always must do it. This requires us to // initialize it with the configured page size. -- GitLab From c9b671a12fd0a875d16712408aa35abaf00a2d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 10 Nov 2015 15:58:17 +0100 Subject: [PATCH 011/344] Handle errors on memcached level - fixes #17397 --- lib/private/memcache/memcached.php | 38 +++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/private/memcache/memcached.php b/lib/private/memcache/memcached.php index ce7c6fa9577..22b54f7bc95 100644 --- a/lib/private/memcache/memcached.php +++ b/lib/private/memcache/memcached.php @@ -41,9 +41,9 @@ class Memcached extends Cache implements IMemcache { parent::__construct($prefix); if (is_null(self::$cache)) { self::$cache = new \Memcached(); - $servers = \OC_Config::getValue('memcached_servers'); + $servers = \OC::$server->getSystemConfig()->getValue('memcached_servers'); if (!$servers) { - $server = \OC_Config::getValue('memcached_server'); + $server = \OC::$server->getSystemConfig()->getValue('memcached_server'); if ($server) { $servers = array($server); } else { @@ -72,10 +72,12 @@ class Memcached extends Cache implements IMemcache { public function set($key, $value, $ttl = 0) { if ($ttl > 0) { - return self::$cache->set($this->getNamespace() . $key, $value, $ttl); + $result = self::$cache->set($this->getNamespace() . $key, $value, $ttl); } else { - return self::$cache->set($this->getNamespace() . $key, $value); + $result = self::$cache->set($this->getNamespace() . $key, $value); } + $this->verifyReturnCode(); + return $result; } public function hasKey($key) { @@ -84,7 +86,9 @@ class Memcached extends Cache implements IMemcache { } public function remove($key) { - return self::$cache->delete($this->getNamespace() . $key); + $result= self::$cache->delete($this->getNamespace() . $key); + $this->verifyReturnCode(); + return $result; } public function clear($prefix = '') { @@ -121,7 +125,9 @@ class Memcached extends Cache implements IMemcache { * @return bool */ public function add($key, $value, $ttl = 0) { - return self::$cache->add($this->getPrefix() . $key, $value, $ttl); + $result = self::$cache->add($this->getPrefix() . $key, $value, $ttl); + $this->verifyReturnCode(); + return $result; } /** @@ -133,7 +139,9 @@ class Memcached extends Cache implements IMemcache { */ public function inc($key, $step = 1) { $this->add($key, 0); - return self::$cache->increment($this->getPrefix() . $key, $step); + $result = self::$cache->increment($this->getPrefix() . $key, $step); + $this->verifyReturnCode(); + return $result; } /** @@ -144,10 +152,24 @@ class Memcached extends Cache implements IMemcache { * @return int | bool */ public function dec($key, $step = 1) { - return self::$cache->decrement($this->getPrefix() . $key, $step); + $result = self::$cache->decrement($this->getPrefix() . $key, $step); + $this->verifyReturnCode(); + return $result; } static public function isAvailable() { return extension_loaded('memcached'); } + + /** + * @throws \Exception + */ + private function verifyReturnCode() { + $code = self::$cache->getResultCode(); + if ($code === \Memcached::RES_SUCCESS) { + return; + } + $message = self::$cache->getResultMessage(); + throw new \Exception("Error $code interacting with memcached : $message"); + } } -- GitLab From 7aeda7c99a44b66ce122d6a24131648438d51d09 Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Wed, 11 Nov 2015 14:21:10 +0000 Subject: [PATCH 012/344] Added a test and logic for checking answer of public shares --- .../features/bootstrap/FeatureContext.php | 78 ++++++++++++++++--- build/integration/features/sharing-v1.feature | 19 +++++ 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 4a0299d6e49..96f46ce28ed 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -562,7 +562,30 @@ class FeatureContext implements Context, SnippetAcceptingContext { * @param \Behat\Gherkin\Node\TableNode|null $formData */ public function createPublicShare($body) { - $this->sendingToWith("POST", "/apps/files_sharing/api/v1/shares", $body); + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v1/shares"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$this->currentUser, $this->regularUser]; + } + + if ($body instanceof \Behat\Gherkin\Node\TableNode) { + $fd = $body->getRowsHash(); + if (array_key_exists('expireDate', $fd)){ + $dateModification = $fd['expireDate']; + $fd['expireDate'] = date('Y-m-d', strtotime($dateModification)); + } + $options['body'] = $fd; + } + + try { + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + } + $this->lastShareData = $this->response->xml(); } @@ -669,17 +692,48 @@ class FeatureContext implements Context, SnippetAcceptingContext { } - public function isFieldInResponse($field, $content_expected){ + public function isExpectedUrl($possibleUrl, $finalPart){ + $baseUrlChopped = substr($this->baseUrl, 0, -4); + $endCharacter = strlen($baseUrlChopped) + strlen($finalPart); + return (substr($possibleUrl,0,$endCharacter) == "$baseUrlChopped" . "$finalPart"); + } + + public function isFieldInResponse($field, $contentExpected){ $data = $this->response->xml()->data[0]; - foreach($data as $element) { - if ($content_expected == "A_NUMBER"){ - return is_numeric((string)$element->$field); - } - elseif ($element->$field == $content_expected){ - return True; + if ((string)$field == 'expiration'){ + $contentExpected = date('Y-m-d', strtotime($contentExpected)) . " 00:00:00"; + } + if (count($data->element) > 0){ + foreach($data as $element) { + if ($contentExpected == "A_TOKEN"){ + return (strlen((string)$element->$field) == 15); + } + elseif ($contentExpected == "A_NUMBER"){ + return is_numeric((string)$element->$field); + } + elseif($contentExpected == "AN_URL"){ + return $this->isExpectedUrl((string)$element->$field, "index.php/s/"); + } + elseif ($element->$field == $contentExpected){ + return True; + } } + return False; + } else { + if ($contentExpected == "A_TOKEN"){ + return (strlen((string)$data->$field) == 15); + } + elseif ($contentExpected == "A_NUMBER"){ + return is_numeric((string)$data->$field); + } + elseif($contentExpected == "AN_URL"){ + return $this->isExpectedUrl((string)$data->$field, "index.php/s/"); + } + elseif ($data->$field == $contentExpected){ + return True; + } + return False; } - return False; } /** @@ -786,6 +840,9 @@ class FeatureContext implements Context, SnippetAcceptingContext { for ($i=0; $i<5; $i++){ file_put_contents("../../core/skeleton/" . "textfile" . "$i" . ".txt", "ownCloud test text file\n"); } + if (!file_exists("../../core/skeleton/FOLDER")) { + mkdir("../../core/skeleton/FOLDER", 0777, true); + } } @@ -796,6 +853,9 @@ class FeatureContext implements Context, SnippetAcceptingContext { for ($i=0; $i<5; $i++){ self::removeFile("../../core/skeleton/", "textfile" . "$i" . ".txt"); } + if (!is_dir("../../core/skeleton/FOLDER")) { + rmdir("../../core/skeleton/FOLDER"); + } } /** diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 36e729d2a13..4ca1966b942 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -46,6 +46,25 @@ Feature: sharing And the HTTP status code should be "200" And Public shared file "welcome.txt" with password "publicpw" can be downloaded + Scenario: Creating a new public share of a folder + Given user "user0" exists + And As an "user0" + When creating a public share with + | path | FOLDER | + | shareType | 3 | + | password | publicpw | + | expireDate | +3 days | + | publicUpload | true | + | permissions | 7 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | permissions | 7 | + | expiration | +3 days | + | url | AN_URL | + | token | A_TOKEN | + Scenario: Creating a new public share with password and adding an expiration date Given user "user0" exists And As an "user0" -- GitLab From 0de225e6a6a98292989d190eb287a10c359f178f Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Wed, 11 Nov 2015 16:44:54 +0100 Subject: [PATCH 013/344] fix layout and wording for file handling admin setting --- apps/files/templates/admin.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/files/templates/admin.php b/apps/files/templates/admin.php index 822fc779bd3..e5a6ecfc96e 100644 --- a/apps/files/templates/admin.php +++ b/apps/files/templates/admin.php @@ -7,14 +7,12 @@ (t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>) -
- t('With PHP-FPM this value may take up to 5 minutes to take effect after saving.')); ?> -
+

t('With PHP-FPM it might take 5 minutes for changes to be applied.')); ?>

- t('Can not be edited from here due to insufficient permissions.')); ?> +

t('Missing permissions to edit from here.')); ?>

-- GitLab From c9753655dca9f3a50ae7556dee95f0d46f27bc90 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 11 Nov 2015 18:18:33 +0100 Subject: [PATCH 014/344] Do not use the asset pipeline when doing updates --- lib/private/template.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/private/template.php b/lib/private/template.php index 38527cdc461..722194dc764 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -379,6 +379,17 @@ class OC_Template extends \OC\Template\Base { * @return bool */ public static function isAssetPipelineEnabled() { + try { + if (\OCP\Util::needUpgrade()) { + // Don't use the compiled asset when we need to do an update + return false; + } + } catch (\Exception $e) { + // Catch any exception, because this code is also called when displaying + // an exception error page. + return false; + } + // asset management enabled? $config = \OC::$server->getConfig(); $useAssetPipeline = $config->getSystemValue('asset-pipeline.enabled', false); -- GitLab From eb6a13c23147eaf7f8aa28cfaacea22ffcf3c43a Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Wed, 11 Nov 2015 17:29:38 +0000 Subject: [PATCH 015/344] Added a test including all the fields of the share update and checking output --- .../features/bootstrap/FeatureContext.php | 51 ++++++++++++++++++- build/integration/features/sharing-v1.feature | 38 +++++++++++++- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 96f46ce28ed..46c86f1300b 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -595,7 +595,12 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function checkPublicSharedFile($filename) { $client = new Client(); $options = []; - $url = $this->lastShareData->data[0]->url; + if (count($this->lastShareData->data->element) > 0){ + $url = $this->lastShareData->data[0]->url; + } + else{ + $url = $this->lastShareData->data->url; + } $fullUrl = $url . "/download"; $options['save_to'] = "./$filename"; $this->response = $client->get($fullUrl, $options); @@ -613,7 +618,13 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function checkPublicSharedFileWithPassword($filename, $password) { $client = new Client(); $options = []; - $token = $this->lastShareData->data[0]->token; + if (count($this->lastShareData->data->element) > 0){ + $token = $this->lastShareData->data[0]->token; + } + else{ + $token = $this->lastShareData->data->token; + } + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav"; $options['auth'] = [$token, $password]; $options['save_to'] = "./$filename"; @@ -645,6 +656,40 @@ class FeatureContext implements Context, SnippetAcceptingContext { PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); } + /** + * @When /^Updating last share with$/ + * @param \Behat\Gherkin\Node\TableNode|null $formData + */ + public function updatingLastShare($body) { + $share_id = $this->lastShareData->data[0]->id; + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$this->currentUser, $this->regularUser]; + } + + if ($body instanceof \Behat\Gherkin\Node\TableNode) { + $fd = $body->getRowsHash(); + if (array_key_exists('expireDate', $fd)){ + $dateModification = $fd['expireDate']; + $fd['expireDate'] = date('Y-m-d', strtotime($dateModification)); + } + $options['body'] = $fd; + } + + try { + $this->response = $client->send($client->createRequest("PUT", $fullUrl, $options)); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + } + + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + public function createShare($user, $path = null, $shareType = null, @@ -718,6 +763,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { return True; } } + return False; } else { if ($contentExpected == "A_TOKEN"){ @@ -821,6 +867,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function checkShareFields($body){ if ($body instanceof \Behat\Gherkin\Node\TableNode) { $fd = $body->getRowsHash(); + foreach($fd as $field => $value) { PHPUnit_Framework_Assert::assertEquals(True, $this->isFieldInResponse($field, $value)); } diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 4ca1966b942..df75a25e8e7 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -72,11 +72,47 @@ Feature: sharing | path | welcome.txt | | shareType | 3 | | password | publicpw | - And Adding expiration date to last share + #And Adding expiration date to last share + And Updating last share with + | expireDate | +3 days | Then the OCS status code should be "100" And the HTTP status code should be "200" And Public shared file "welcome.txt" with password "publicpw" can be downloaded + Scenario: Creating a new public share, updating it and getting it's info + Given user "user0" exists + And As an "user0" + When creating a public share with + | path | FOLDER | + | shareType | 3 | + And Updating last share with + | expireDate | +3 days | + | password | publicpw | + | publicUpload | true | + | permissions | 7 | + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | folder | + | item_source | A_NUMBER | + | share_type | 3 | + | file_source | A_NUMBER | + | file_target | /FOLDER | + | permissions | 7 | + | stime | A_NUMBER | + | expiration | +3 days | + | token | A_TOKEN | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | displayname_owner | user0 | + | url | AN_URL | + + Scenario: getting all shares of a user using that user Given user "user0" exists And user "user1" exists -- GitLab From ff17deecd213f0749d37a98aa55112b4caf9aca4 Mon Sep 17 00:00:00 2001 From: sylvain Date: Thu, 12 Nov 2015 15:39:57 +0900 Subject: [PATCH 016/344] changed 1.000 to 1,000 The string "More than 1,000 directory entries available." would mean only 1 entry, in english it should be 1,000 . Found it while translating --- apps/user_ldap/js/wizard/wizardTabElementary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/js/wizard/wizardTabElementary.js b/apps/user_ldap/js/wizard/wizardTabElementary.js index f5232e91010..c8cb308952b 100644 --- a/apps/user_ldap/js/wizard/wizardTabElementary.js +++ b/apps/user_ldap/js/wizard/wizardTabElementary.js @@ -275,7 +275,7 @@ OCA = OCA || {}; if(objectsFound < 1) { message = t('user_ldap', 'No object found in the given Base DN. Please revise.'); } else if(objectsFound > 1000) { - message = t('user_ldap', 'More than 1.000 directory entries available.'); + message = t('user_ldap', 'More than 1,000 directory entries available.'); } else { message = t('user_ldap', objectsFound + ' entries available within the provided Base DN'); } -- GitLab From 9145aa607a221d3c223c33989cff05fff37f4182 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Thu, 12 Nov 2015 01:55:09 -0500 Subject: [PATCH 017/344] [tx-robot] updated from transifex --- apps/files_trashbin/l10n/ast.js | 2 ++ apps/files_trashbin/l10n/ast.json | 2 ++ lib/l10n/ast.js | 9 +++++++++ lib/l10n/ast.json | 9 +++++++++ lib/l10n/fi_FI.js | 3 +++ lib/l10n/fi_FI.json | 3 +++ lib/l10n/sq.js | 1 + lib/l10n/sq.json | 1 + 8 files changed, 30 insertions(+) diff --git a/apps/files_trashbin/l10n/ast.js b/apps/files_trashbin/l10n/ast.js index 5df7fb84547..b467f8b51a1 100644 --- a/apps/files_trashbin/l10n/ast.js +++ b/apps/files_trashbin/l10n/ast.js @@ -9,6 +9,8 @@ OC.L10N.register( "Delete permanently" : "Desaniciar dafechu", "Error" : "Fallu", "restored" : "recuperóse", + "No deleted files" : "Ensin ficheros desaniciaos", + "You will be able to recover deleted files from here" : "Dende equí podrás recureperar los ficheros desaniciaos", "No entries found in this folder" : "Nenguna entrada en esta carpeta", "Select all" : "Esbillar too", "Name" : "Nome", diff --git a/apps/files_trashbin/l10n/ast.json b/apps/files_trashbin/l10n/ast.json index 4268ef6bc21..b568456279b 100644 --- a/apps/files_trashbin/l10n/ast.json +++ b/apps/files_trashbin/l10n/ast.json @@ -7,6 +7,8 @@ "Delete permanently" : "Desaniciar dafechu", "Error" : "Fallu", "restored" : "recuperóse", + "No deleted files" : "Ensin ficheros desaniciaos", + "You will be able to recover deleted files from here" : "Dende equí podrás recureperar los ficheros desaniciaos", "No entries found in this folder" : "Nenguna entrada en esta carpeta", "Select all" : "Esbillar too", "Name" : "Nome", diff --git a/lib/l10n/ast.js b/lib/l10n/ast.js index bd47f46ca0a..c3ca33e74ad 100644 --- a/lib/l10n/ast.js +++ b/lib/l10n/ast.js @@ -8,6 +8,15 @@ OC.L10N.register( "Sample configuration detected" : "Configuración d'amuesa detectada", "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" : "Detectose que la configuración d'amuesa copiose. Esto pue encaboxar la instalación y dexala ensín soporte. Llee la documentación enantes de facer cambéos en config.php", "PHP %s or higher is required." : "Necesítase PHP %s o superior", + "PHP with a version lower than %s is required." : "Necesítase una versión PHP anterior a %s", + "Following databases are supported: %s" : "Les siguientes bases de datos tan sofitaes: %s", + "The command line tool %s could not be found" : "La ferramienta línea de comandu %s nun pudo alcontrase", + "The library %s is not available." : "La librería %s nun ta disponible", + "Library %s with a version higher than %s is required - available version %s." : "Necesítase una librería %s con ua versión superior a %s - versión disponible %s.", + "Library %s with a version lower than %s is required - available version %s." : "Necesítase una librería %s con una versión anterior a %s - versión disponible %s.", + "Following platforms are supported: %s" : "Les siguientes plataformes tan sofitaes: %s", + "ownCloud %s or higher is required." : "Necesítase ownCloud %s o superior.", + "ownCloud %s or lower is required." : "Necesítase ownCloud %s o anterior.", "Help" : "Ayuda", "Personal" : "Personal", "Users" : "Usuarios", diff --git a/lib/l10n/ast.json b/lib/l10n/ast.json index 892a99d9c3d..bfcaf8729d7 100644 --- a/lib/l10n/ast.json +++ b/lib/l10n/ast.json @@ -6,6 +6,15 @@ "Sample configuration detected" : "Configuración d'amuesa detectada", "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" : "Detectose que la configuración d'amuesa copiose. Esto pue encaboxar la instalación y dexala ensín soporte. Llee la documentación enantes de facer cambéos en config.php", "PHP %s or higher is required." : "Necesítase PHP %s o superior", + "PHP with a version lower than %s is required." : "Necesítase una versión PHP anterior a %s", + "Following databases are supported: %s" : "Les siguientes bases de datos tan sofitaes: %s", + "The command line tool %s could not be found" : "La ferramienta línea de comandu %s nun pudo alcontrase", + "The library %s is not available." : "La librería %s nun ta disponible", + "Library %s with a version higher than %s is required - available version %s." : "Necesítase una librería %s con ua versión superior a %s - versión disponible %s.", + "Library %s with a version lower than %s is required - available version %s." : "Necesítase una librería %s con una versión anterior a %s - versión disponible %s.", + "Following platforms are supported: %s" : "Les siguientes plataformes tan sofitaes: %s", + "ownCloud %s or higher is required." : "Necesítase ownCloud %s o superior.", + "ownCloud %s or lower is required." : "Necesítase ownCloud %s o anterior.", "Help" : "Ayuda", "Personal" : "Personal", "Users" : "Usuarios", diff --git a/lib/l10n/fi_FI.js b/lib/l10n/fi_FI.js index 9172c250e0d..c932fa35d60 100644 --- a/lib/l10n/fi_FI.js +++ b/lib/l10n/fi_FI.js @@ -79,6 +79,7 @@ OC.L10N.register( "%s shared »%s« with you" : "%s jakoi kohteen »%s« kanssasi", "Sharing %s failed, because the file does not exist" : "Kohteen %s jakaminen epäonnistui, koska tiedostoa ei ole olemassa", "You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.", + "Sharing %s failed, because you can not share with yourself" : "Kohteen %s jakaminen epäonnistui, koska et voi jakaa itsesi kanssa", "Sharing %s failed, because the user %s does not exist" : "Kohteen %s jakaminen epäonnistui, koska käyttäjää %s ei ole olemassa", "Sharing %s failed, because this item is already shared with %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", "Sharing %s failed, because this item is already shared with user %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", @@ -92,6 +93,7 @@ OC.L10N.register( "Cannot clear expiration date. Shares are required to have an expiration date." : "Vanhenemispäivän tyhjentäminen ei onnistu. Jaoille on määritelty pakolliseksi vanhenemispäivä.", "Sharing backend %s not found" : "Jakamisen taustaosaa %s ei löytynyt", "Sharing backend for %s not found" : "Jakamisen taustaosaa kohteelle %s ei löytynyt", + "Sharing failed, because the user %s is the original sharer" : "Jakaminen epäonnistui, koska käyttäjä %s ei ole alkuperäinen jakaja", "Sharing %s failed, because resharing is not allowed" : "Kohteen %s jakaminen epäonnistui, koska jakaminen uudelleen ei ole sallittu", "Sharing %s failed, because the file could not be found in the file cache" : "Kohteen %s jakaminen epäonnistui, koska tiedostoa ei löytynyt tiedostovälimuistista", "Could not find category \"%s\"" : "Luokkaa \"%s\" ei löytynyt", @@ -105,6 +107,7 @@ OC.L10N.register( "Running ownCloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself. Find Linux packages as well as easy to deploy virtual machine images on %s. For migrating existing installations to Linux you can find some tips and a migration script in our documentation." : "ownCloud-palvelin ei ole tuettu Microsoft Windows -alustalla. Suosittelemme käyttämään Linux-palvelinta virtuaalikoneessa, jos itse palvelimeen ei voi asentaa Linux-jakelua käyttöjärjestelmäksi. Linux-paketit ja virtuaalikoneiden levykuvat ovat saatavilla osoitteesta %s. Tarjoamme vinkkejä ja siirtoskriptejä nykyisten asennusten siirtämiseksi Linux-alustalle dokumenaation kautta.", "Cannot write into \"config\" directory" : "Hakemistoon \"config\" kirjoittaminen ei onnistu", "Cannot write into \"apps\" directory" : "Hakemistoon \"apps\" kirjoittaminen ei onnistu", + "This can usually be fixed by %sgiving the webserver write access to the apps directory%s or disabling the appstore in the config file." : "Tämä on yleensä mahdollista korjata %santamalla HTTP-palvelimelle kirjoitusoikeus sovellushakemistoon%s tai poistamalla sovelluskauppa pois käytöstä asetustiedostoa käyttäen.", "Cannot create \"data\" directory (%s)" : "Kansion \"data\" luominen ei onnistu (%s)", "This can usually be fixed by giving the webserver write access to the root directory." : "Tämä on yleensä korjattavissa antamalla http-palvelimelle kirjoitusoikeuden juurihakemistoon.", "Setting locale to %s failed" : "Maa-asetuksen %s asettaminen epäonnistui", diff --git a/lib/l10n/fi_FI.json b/lib/l10n/fi_FI.json index b5455341543..55209ee0b72 100644 --- a/lib/l10n/fi_FI.json +++ b/lib/l10n/fi_FI.json @@ -77,6 +77,7 @@ "%s shared »%s« with you" : "%s jakoi kohteen »%s« kanssasi", "Sharing %s failed, because the file does not exist" : "Kohteen %s jakaminen epäonnistui, koska tiedostoa ei ole olemassa", "You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.", + "Sharing %s failed, because you can not share with yourself" : "Kohteen %s jakaminen epäonnistui, koska et voi jakaa itsesi kanssa", "Sharing %s failed, because the user %s does not exist" : "Kohteen %s jakaminen epäonnistui, koska käyttäjää %s ei ole olemassa", "Sharing %s failed, because this item is already shared with %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", "Sharing %s failed, because this item is already shared with user %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", @@ -90,6 +91,7 @@ "Cannot clear expiration date. Shares are required to have an expiration date." : "Vanhenemispäivän tyhjentäminen ei onnistu. Jaoille on määritelty pakolliseksi vanhenemispäivä.", "Sharing backend %s not found" : "Jakamisen taustaosaa %s ei löytynyt", "Sharing backend for %s not found" : "Jakamisen taustaosaa kohteelle %s ei löytynyt", + "Sharing failed, because the user %s is the original sharer" : "Jakaminen epäonnistui, koska käyttäjä %s ei ole alkuperäinen jakaja", "Sharing %s failed, because resharing is not allowed" : "Kohteen %s jakaminen epäonnistui, koska jakaminen uudelleen ei ole sallittu", "Sharing %s failed, because the file could not be found in the file cache" : "Kohteen %s jakaminen epäonnistui, koska tiedostoa ei löytynyt tiedostovälimuistista", "Could not find category \"%s\"" : "Luokkaa \"%s\" ei löytynyt", @@ -103,6 +105,7 @@ "Running ownCloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself. Find Linux packages as well as easy to deploy virtual machine images on %s. For migrating existing installations to Linux you can find some tips and a migration script in our documentation." : "ownCloud-palvelin ei ole tuettu Microsoft Windows -alustalla. Suosittelemme käyttämään Linux-palvelinta virtuaalikoneessa, jos itse palvelimeen ei voi asentaa Linux-jakelua käyttöjärjestelmäksi. Linux-paketit ja virtuaalikoneiden levykuvat ovat saatavilla osoitteesta %s. Tarjoamme vinkkejä ja siirtoskriptejä nykyisten asennusten siirtämiseksi Linux-alustalle dokumenaation kautta.", "Cannot write into \"config\" directory" : "Hakemistoon \"config\" kirjoittaminen ei onnistu", "Cannot write into \"apps\" directory" : "Hakemistoon \"apps\" kirjoittaminen ei onnistu", + "This can usually be fixed by %sgiving the webserver write access to the apps directory%s or disabling the appstore in the config file." : "Tämä on yleensä mahdollista korjata %santamalla HTTP-palvelimelle kirjoitusoikeus sovellushakemistoon%s tai poistamalla sovelluskauppa pois käytöstä asetustiedostoa käyttäen.", "Cannot create \"data\" directory (%s)" : "Kansion \"data\" luominen ei onnistu (%s)", "This can usually be fixed by giving the webserver write access to the root directory." : "Tämä on yleensä korjattavissa antamalla http-palvelimelle kirjoitusoikeuden juurihakemistoon.", "Setting locale to %s failed" : "Maa-asetuksen %s asettaminen epäonnistui", diff --git a/lib/l10n/sq.js b/lib/l10n/sq.js index cc04707c57e..2cf6eeecdef 100644 --- a/lib/l10n/sq.js +++ b/lib/l10n/sq.js @@ -148,6 +148,7 @@ OC.L10N.register( "Check the value of \"datadirectory\" in your configuration" : "Kontrolloni vlerën e \"datadirectory\" te formësimi juaj", "Data directory (%s) is invalid" : "Drejtoria e të dhënave (%s) është e pavlefshme", "Please check that the data directory contains a file \".ocdata\" in its root." : "Ju lutemi, kontrolloni që drejtoria e të dhënave përmban në rrënjën e saj një kartelë \".ocdata\".", + "Could not obtain lock type %d on \"%s\"." : "S’u mor dot lloj kyçjeje %d në \"%s\".", "Storage not available" : "Pa depozitë gati" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/sq.json b/lib/l10n/sq.json index 1de075e8860..ec412dfff53 100644 --- a/lib/l10n/sq.json +++ b/lib/l10n/sq.json @@ -146,6 +146,7 @@ "Check the value of \"datadirectory\" in your configuration" : "Kontrolloni vlerën e \"datadirectory\" te formësimi juaj", "Data directory (%s) is invalid" : "Drejtoria e të dhënave (%s) është e pavlefshme", "Please check that the data directory contains a file \".ocdata\" in its root." : "Ju lutemi, kontrolloni që drejtoria e të dhënave përmban në rrënjën e saj një kartelë \".ocdata\".", + "Could not obtain lock type %d on \"%s\"." : "S’u mor dot lloj kyçjeje %d në \"%s\".", "Storage not available" : "Pa depozitë gati" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file -- GitLab From d0464bf7724480d18d1f0b881acf83849d83b72d Mon Sep 17 00:00:00 2001 From: Christian Schnidrig Date: Thu, 10 Sep 2015 23:02:28 +0200 Subject: [PATCH 018/344] enable microseconds in log timestamps --- lib/private/log/owncloud.php | 2 +- tests/lib/log/owncloud.php | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/lib/log/owncloud.php diff --git a/lib/private/log/owncloud.php b/lib/private/log/owncloud.php index c98f21208bb..1af989588d1 100644 --- a/lib/private/log/owncloud.php +++ b/lib/private/log/owncloud.php @@ -72,7 +72,7 @@ class OC_Log_Owncloud { } catch (Exception $e) { $timezone = new DateTimeZone('UTC'); } - $time = new DateTime(null, $timezone); + $time = DateTime::createFromFormat("U.u", microtime(true), $timezone); $request = \OC::$server->getRequest(); $reqId = $request->getId(); $remoteAddr = $request->getRemoteAddress(); diff --git a/tests/lib/log/owncloud.php b/tests/lib/log/owncloud.php new file mode 100644 index 00000000000..d977583612b --- /dev/null +++ b/tests/lib/log/owncloud.php @@ -0,0 +1,67 @@ +. + */ + +class Test_Log_Owncloud extends Test\TestCase +{ + private $restore_logfile; + private $restore_logdateformat; + + protected function setUp() { + parent::setUp(); + $restore_logfile = OC_Config::getValue("logfile"); + $restore_logdateformat = OC_Config::getValue('logdateformat'); + + OC_Config::setValue("logfile", OC_Config::getValue('datadirectory') . "/logtest"); + OC_Log_Owncloud::init(); + } + protected function tearDown() { + if (isset($this->restore_logfile)) { + OC_Config::setValue("logfile", $this->restore_logfile); + } else { + OC_Config::deleteKey("logfile"); + } + if (isset($this->restore_logdateformat)) { + OC_Config::setValue("logdateformat", $this->restore_logdateformat); + } else { + OC_Config::deleteKey("restore_logdateformat"); + } + OC_Log_Owncloud::init(); + parent::tearDown(); + } + + public function testMicrosecondsLogTimestamp() { + # delete old logfile + unlink(OC_Config::getValue('logfile')); + + # set format & write log line + OC_Config::setValue('logdateformat', 'u'); + OC_Log_Owncloud::write('test', 'message', \OCP\Util::ERROR); + + # read log line + $handle = @fopen(OC_Config::getValue('logfile'), 'r'); + $line = fread($handle, 1000); + fclose($handle); + + # check timestamp has microseconds part + $values = (array) json_decode($line); + $microseconds = $values['time']; + $this->assertNotEquals(0, $microseconds); + + } + + +} -- GitLab From ce8435530ba87c3574352d479d531caf2e0ab668 Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Thu, 12 Nov 2015 10:36:17 +0000 Subject: [PATCH 019/344] Modified test to PUT only 1 parameter with each update --- build/integration/features/sharing-v1.feature | 90 ++++++++++++++++++- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index df75a25e8e7..07c05af2f54 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -72,14 +72,13 @@ Feature: sharing | path | welcome.txt | | shareType | 3 | | password | publicpw | - #And Adding expiration date to last share And Updating last share with | expireDate | +3 days | Then the OCS status code should be "100" And the HTTP status code should be "200" And Public shared file "welcome.txt" with password "publicpw" can be downloaded - Scenario: Creating a new public share, updating it and getting it's info + Scenario: Creating a new public share, updating its expiration date and getting its info Given user "user0" exists And As an "user0" When creating a public share with @@ -87,8 +86,64 @@ Feature: sharing | shareType | 3 | And Updating last share with | expireDate | +3 days | + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | folder | + | item_source | A_NUMBER | + | share_type | 3 | + | file_source | A_NUMBER | + | file_target | /FOLDER | + | permissions | 1 | + | stime | A_NUMBER | + | expiration | +3 days | + | token | A_TOKEN | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | displayname_owner | user0 | + | url | AN_URL | + + Scenario: Creating a new public share, updating its password and getting its info + Given user "user0" exists + And As an "user0" + When creating a public share with + | path | FOLDER | + | shareType | 3 | + And Updating last share with | password | publicpw | - | publicUpload | true | + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | folder | + | item_source | A_NUMBER | + | share_type | 3 | + | file_source | A_NUMBER | + | file_target | /FOLDER | + | permissions | 1 | + | stime | A_NUMBER | + | token | A_TOKEN | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | displayname_owner | user0 | + | url | AN_URL | + + Scenario: Creating a new public share, updating its permissions and getting its info + Given user "user0" exists + And As an "user0" + When creating a public share with + | path | FOLDER | + | shareType | 3 | + And Updating last share with | permissions | 7 | And Getting info of last share Then the OCS status code should be "100" @@ -102,7 +157,6 @@ Feature: sharing | file_target | /FOLDER | | permissions | 7 | | stime | A_NUMBER | - | expiration | +3 days | | token | A_TOKEN | | storage | A_NUMBER | | mail_send | 0 | @@ -112,6 +166,34 @@ Feature: sharing | displayname_owner | user0 | | url | AN_URL | + Scenario: Creating a new public share, updating publicUpload option and getting its info + Given user "user0" exists + And As an "user0" + When creating a public share with + | path | FOLDER | + | shareType | 3 | + And Updating last share with + | publicUpload | true | + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | folder | + | item_source | A_NUMBER | + | share_type | 3 | + | file_source | A_NUMBER | + | file_target | /FOLDER | + | permissions | 7 | + | stime | A_NUMBER | + | token | A_TOKEN | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | displayname_owner | user0 | + | url | AN_URL | Scenario: getting all shares of a user using that user Given user "user0" exists -- GitLab From 089cd56e00fff6a664d10710e95ffccf6762f12f Mon Sep 17 00:00:00 2001 From: Hendrik Leppelsack Date: Mon, 21 Sep 2015 11:01:19 +0200 Subject: [PATCH 020/344] add Ctrl+F shortcut for the search bar --- core/search/js/search.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/search/js/search.js b/core/search/js/search.js index 4e83a070170..92cf034cf7d 100644 --- a/core/search/js/search.js +++ b/core/search/js/search.js @@ -343,6 +343,13 @@ } }); + $(document).keydown(function(event) { + if ((event.ctrlKey || event.metaKey) && !event.shiftKey && event.keyCode === 70) { // Ctrl+F + $searchBox.focus(); + event.preventDefault(); + } + }); + $searchResults.on('click', 'tr.result', function (event) { var $row = $(this); var item = $row.data('result'); -- GitLab From b167eb743fa2f844e5e39a330e628c6bf54d4975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Weigert?= Date: Thu, 12 Nov 2015 14:33:59 +0100 Subject: [PATCH 021/344] Update untrustedDomain.php --- core/templates/untrustedDomain.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/templates/untrustedDomain.php b/core/templates/untrustedDomain.php index 3197916cebb..361495636cd 100644 --- a/core/templates/untrustedDomain.php +++ b/core/templates/untrustedDomain.php @@ -5,7 +5,7 @@ t('You are accessing the server from an untrusted domain.')); ?>

- t('Please contact your administrator. If you are an administrator of this instance, configure the "trusted_domain" setting in config/config.php. An example configuration is provided in config/config.sample.php.')); ?> + t('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.')); ?>
t('Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain.')); ?>

-- GitLab From 3b88c469c781e5255663e81c7c6b0459cbba34b2 Mon Sep 17 00:00:00 2001 From: michag86 Date: Thu, 27 Aug 2015 18:29:28 +0200 Subject: [PATCH 022/344] enable api addUser for subadmins * Fix existing unit tests --- apps/provisioning_api/appinfo/routes.php | 2 +- apps/provisioning_api/lib/users.php | 44 +++++++++++++++++++---- apps/provisioning_api/tests/userstest.php | 42 ++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php index dcf18e0e53b..d2cba549846 100644 --- a/apps/provisioning_api/appinfo/routes.php +++ b/apps/provisioning_api/appinfo/routes.php @@ -37,7 +37,7 @@ $users = new \OCA\Provisioning_API\Users( \OC::$server->getLogger() ); API::register('get', '/cloud/users', [$users, 'getUsers'], 'provisioning_api', API::SUBADMIN_AUTH); -API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::ADMIN_AUTH); +API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::SUBADMIN_AUTH); API::register('get', '/cloud/users/{userid}', [$users, 'getUser'], 'provisioning_api', API::USER_AUTH); API::register('put', '/cloud/users/{userid}', [$users, 'editUser'], 'provisioning_api', API::USER_AUTH); API::register('delete', '/cloud/users/{userid}', [$users, 'deleteUser'], 'provisioning_api', API::SUBADMIN_AUTH); diff --git a/apps/provisioning_api/lib/users.php b/apps/provisioning_api/lib/users.php index 304fe901cfd..49199d4169c 100644 --- a/apps/provisioning_api/lib/users.php +++ b/apps/provisioning_api/lib/users.php @@ -117,18 +117,48 @@ class Users { public function addUser() { $userId = isset($_POST['userid']) ? $_POST['userid'] : null; $password = isset($_POST['password']) ? $_POST['password'] : null; + $groups = isset($_POST['groups']) ? $_POST['groups'] : null; + $user = $this->userSession->getUser(); + $isAdmin = $this->groupManager->isAdmin($user->getUID()); + + if (!$isAdmin && !$this->groupManager->getSubAdmin()->isSubAdmin($user)) { + return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + } + if($this->userManager->userExists($userId)) { $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']); return new OC_OCS_Result(null, 102, 'User already exists'); + } + + if(is_array($groups)) { + foreach ($groups as $key => $group) { + if(!$this->groupManager->groupExists($group)){ + return new OC_OCS_Result(null, 104, 'group '.$group.' does not exist'); + } + if(!$isAdmin && !$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $this->groupManager->get($group))) { + return new OC_OCS_Result(null, 105, 'insufficient privileges for group '. $group); + } + } } else { - try { - $this->userManager->createUser($userId, $password); - $this->logger->info('Successful addUser call with userid: '.$_POST['userid'], ['app' => 'ocs_api']); - return new OC_OCS_Result(null, 100); - } catch (\Exception $e) { - $this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']); - return new OC_OCS_Result(null, 101, 'Bad request'); + if(!$isAdmin) { + return new OC_OCS_Result(null, 106, 'no group specified (required for subadmins)'); + } + } + + try { + $user = $this->userManager->createUser($userId, $password); + $this->logger->info('Successful addUser call with userid: '.$_POST['userid'], ['app' => 'ocs_api']); + + if (is_array($groups)) { + foreach ($groups as $group) { + $this->groupManager->get($group)->addUser($user); + $this->logger->info('Added user (' . $user->getUID() . ') to group ' . $group, ['app' => 'ocs_api']); + } } + return new OC_OCS_Result(null, 100); + } catch (\Exception $e) { + $this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']); + return new OC_OCS_Result(null, 101, 'Bad request'); } } diff --git a/apps/provisioning_api/tests/userstest.php b/apps/provisioning_api/tests/userstest.php index ba4ed8a2e2f..12b04c0c826 100644 --- a/apps/provisioning_api/tests/userstest.php +++ b/apps/provisioning_api/tests/userstest.php @@ -218,6 +218,20 @@ class UsersTest extends OriginalTest { ->expects($this->once()) ->method('error') ->with('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); $expected = new \OC_OCS_Result(null, 102, 'User already exists'); $this->assertEquals($expected, $this->api->addUser()); @@ -239,6 +253,20 @@ class UsersTest extends OriginalTest { ->expects($this->once()) ->method('info') ->with('Successful addUser call with userid: NewUser', ['app' => 'ocs_api']); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); $expected = new \OC_OCS_Result(null, 100); $this->assertEquals($expected, $this->api->addUser()); @@ -261,6 +289,20 @@ class UsersTest extends OriginalTest { ->expects($this->once()) ->method('error') ->with('Failed addUser attempt with exception: User backend not found.', ['app' => 'ocs_api']); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); $expected = new \OC_OCS_Result(null, 101, 'Bad request'); $this->assertEquals($expected, $this->api->addUser()); -- GitLab From fc1f0233ffd777220c3128a0e727041c4c62ac72 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 30 Oct 2015 09:30:00 +0100 Subject: [PATCH 023/344] Added unit test for new functionality --- apps/provisioning_api/lib/users.php | 15 +- apps/provisioning_api/tests/userstest.php | 339 ++++++++++++++++++++++ 2 files changed, 347 insertions(+), 7 deletions(-) diff --git a/apps/provisioning_api/lib/users.php b/apps/provisioning_api/lib/users.php index 49199d4169c..a2568425d0f 100644 --- a/apps/provisioning_api/lib/users.php +++ b/apps/provisioning_api/lib/users.php @@ -120,8 +120,9 @@ class Users { $groups = isset($_POST['groups']) ? $_POST['groups'] : null; $user = $this->userSession->getUser(); $isAdmin = $this->groupManager->isAdmin($user->getUID()); + $subAdminManager = $this->groupManager->getSubAdmin(); - if (!$isAdmin && !$this->groupManager->getSubAdmin()->isSubAdmin($user)) { + if (!$isAdmin && !$subAdminManager->isSubAdmin($user)) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } @@ -131,11 +132,11 @@ class Users { } if(is_array($groups)) { - foreach ($groups as $key => $group) { + foreach ($groups as $group) { if(!$this->groupManager->groupExists($group)){ return new OC_OCS_Result(null, 104, 'group '.$group.' does not exist'); } - if(!$isAdmin && !$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $this->groupManager->get($group))) { + if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) { return new OC_OCS_Result(null, 105, 'insufficient privileges for group '. $group); } } @@ -146,13 +147,13 @@ class Users { } try { - $user = $this->userManager->createUser($userId, $password); - $this->logger->info('Successful addUser call with userid: '.$_POST['userid'], ['app' => 'ocs_api']); + $newUser = $this->userManager->createUser($userId, $password); + $this->logger->info('Successful addUser call with userid: '.$userId, ['app' => 'ocs_api']); if (is_array($groups)) { foreach ($groups as $group) { - $this->groupManager->get($group)->addUser($user); - $this->logger->info('Added user (' . $user->getUID() . ') to group ' . $group, ['app' => 'ocs_api']); + $this->groupManager->get($group)->addUser($newUser); + $this->logger->info('Added userid '.$userId.' to group '.$group, ['app' => 'ocs_api']); } } return new OC_OCS_Result(null, 100); diff --git a/apps/provisioning_api/tests/userstest.php b/apps/provisioning_api/tests/userstest.php index 12b04c0c826..63180eb3472 100644 --- a/apps/provisioning_api/tests/userstest.php +++ b/apps/provisioning_api/tests/userstest.php @@ -237,6 +237,76 @@ class UsersTest extends OriginalTest { $this->assertEquals($expected, $this->api->addUser()); } + public function testAddUserNonExistingGroup() { + $_POST['userid'] = 'NewUser'; + $_POST['groups'] = ['NonExistingGroup']; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->willReturn(false); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + $this->groupManager + ->expects($this->once()) + ->method('groupExists') + ->with('NonExistingGroup') + ->willReturn(false); + + $expected = new \OC_OCS_Result(null, 104, 'group NonExistingGroup does not exist'); + $this->assertEquals($expected, $this->api->addUser()); + } + + public function testAddUserExistingGroupNonExistingGroup() { + $_POST['userid'] = 'NewUser'; + $_POST['groups'] = ['ExistingGroup', 'NonExistingGroup']; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->willReturn(false); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + $this->groupManager + ->expects($this->exactly(2)) + ->method('groupExists') + ->withConsecutive( + ['ExistingGroup'], + ['NonExistingGroup'] + ) + ->will($this->returnValueMap([ + ['ExistingGroup', true], + ['NonExistingGroup', false] + ])); + + $expected = new \OC_OCS_Result(null, 104, 'group NonExistingGroup does not exist'); + $this->assertEquals($expected, $this->api->addUser()); + } + public function testAddUserSuccessful() { $_POST['userid'] = 'NewUser'; $_POST['password'] = 'PasswordOfTheNewUser'; @@ -272,6 +342,62 @@ class UsersTest extends OriginalTest { $this->assertEquals($expected, $this->api->addUser()); } + public function testAddUserExistingGroup() { + $_POST['userid'] = 'NewUser'; + $_POST['password'] = 'PasswordOfTheNewUser'; + $_POST['groups'] = ['ExistingGroup']; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->willReturn(false); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + $this->groupManager + ->expects($this->once()) + ->method('groupExists') + ->with('ExistingGroup') + ->willReturn(true); + $user = $this->getMock('\OCP\IUser'); + $this->userManager + ->expects($this->once()) + ->method('createUser') + ->with('NewUser', 'PasswordOfTheNewUser') + ->willReturn($user); + $group = $this->getMock('\OCP\IGroup'); + $group + ->expects($this->once()) + ->method('addUser') + ->with($user); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('ExistingGroup') + ->willReturn($group); + $this->logger + ->expects($this->exactly(2)) + ->method('info') + ->withConsecutive( + ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']], + ['Added userid NewUser to group ExistingGroup', ['app' => 'ocs_api']] + ); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->addUser()); + } + public function testAddUserUnsuccessful() { $_POST['userid'] = 'NewUser'; $_POST['password'] = 'PasswordOfTheNewUser'; @@ -308,6 +434,219 @@ class UsersTest extends OriginalTest { $this->assertEquals($expected, $this->api->addUser()); } + public function testAddUserAsRegularUser() { + $_POST['userid'] = 'NewUser'; + $_POST['password'] = 'PasswordOfTheNewUser'; + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('regularUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('regularUser') + ->willReturn(false); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->willReturn(false); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->with() + ->willReturn($subAdminManager); + + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + $this->assertEquals($expected, $this->api->addUser()); + } + + public function testAddUserAsSubAdminNoGroup() { + $_POST['userid'] = 'NewUser'; + $_POST['password'] = 'PasswordOfTheNewUser'; + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('regularUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('regularUser') + ->willReturn(false); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->willReturn(true); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->with() + ->willReturn($subAdminManager); + + $expected = new \OC_OCS_Result(null, 106, 'no group specified (required for subadmins)'); + $this->assertEquals($expected, $this->api->addUser()); + } + + public function testAddUserAsSubAdminValidGroupNotSubAdmin() { + $_POST['userid'] = 'NewUser'; + $_POST['password'] = 'PasswordOfTheNewUser'; + $_POST['groups'] = ['ExistingGroup']; + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('regularUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('regularUser') + ->willReturn(false); + $existingGroup = $this->getMock('\OCP\IGroup'); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('ExistingGroup') + ->willReturn($existingGroup); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->willReturn(true); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($loggedInUser, $existingGroup) + ->wilLReturn(false); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->with() + ->willReturn($subAdminManager); + $this->groupManager + ->expects($this->once()) + ->method('groupExists') + ->with('ExistingGroup') + ->willReturn(true); + + $expected = new \OC_OCS_Result(null, 105, 'insufficient privileges for group ExistingGroup'); + $this->assertEquals($expected, $this->api->addUser()); + } + + public function testAddUserAsSubAdminExistingGroups() { + $_POST['userid'] = 'NewUser'; + $_POST['password'] = 'PasswordOfTheNewUser'; + $_POST['groups'] = ['ExistingGroup1', 'ExistingGroup2']; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->willReturn(false); + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('subAdminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subAdminUser') + ->willReturn(false); + $this->groupManager + ->expects($this->exactly(2)) + ->method('groupExists') + ->withConsecutive( + ['ExistingGroup1'], + ['ExistingGroup2'] + ) + ->willReturn(true); + $user = $this->getMock('\OCP\IUser'); + $this->userManager + ->expects($this->once()) + ->method('createUser') + ->with('NewUser', 'PasswordOfTheNewUser') + ->willReturn($user); + $existingGroup1 = $this->getMock('\OCP\IGroup'); + $existingGroup2 = $this->getMock('\OCP\IGroup'); + $existingGroup1 + ->expects($this->once()) + ->method('addUser') + ->with($user); + $existingGroup2 + ->expects($this->once()) + ->method('addUser') + ->with($user); + $this->groupManager + ->expects($this->exactly(4)) + ->method('get') + ->withConsecutive( + ['ExistingGroup1'], + ['ExistingGroup2'], + ['ExistingGroup1'], + ['ExistingGroup2'] + ) + ->will($this->returnValueMap([ + ['ExistingGroup1', $existingGroup1], + ['ExistingGroup2', $existingGroup2] + ])); + $this->logger + ->expects($this->exactly(3)) + ->method('info') + ->withConsecutive( + ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']], + ['Added userid NewUser to group ExistingGroup1', ['app' => 'ocs_api']], + ['Added userid NewUser to group ExistingGroup2', ['app' => 'ocs_api']] + ); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->willReturn($subAdminManager); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->willReturn(true); + $subAdminManager + ->expects($this->exactly(2)) + ->method('isSubAdminOfGroup') + ->withConsecutive( + [$loggedInUser, $existingGroup1], + [$loggedInUser, $existingGroup2] + ) + ->wilLReturn(true); + + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->addUser()); + } + + public function testGetUserNotLoggedIn() { $this->userSession ->expects($this->once()) -- GitLab From 7ab56de58b85b3649bf865e950afad29f7b5cb90 Mon Sep 17 00:00:00 2001 From: Hendrik Leppelsack Date: Wed, 11 Nov 2015 19:41:36 +0100 Subject: [PATCH 024/344] move form styles from styles.css to inputs.css --- core/css/inputs.css | 232 +++++++++++++++++++++++++++++++++++++ core/css/styles.css | 244 +-------------------------------------- lib/private/template.php | 1 + 3 files changed, 235 insertions(+), 242 deletions(-) create mode 100644 core/css/inputs.css diff --git a/core/css/inputs.css b/core/css/inputs.css new file mode 100644 index 00000000000..9f440a6c359 --- /dev/null +++ b/core/css/inputs.css @@ -0,0 +1,232 @@ +/* INPUTS */ + +/* specifically override browser styles */ +input, textarea, select, button { + font-family: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif; +} + +input[type="text"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="time"], +input[type="date"], +textarea, +select, +button, .button, +input[type="submit"], +input[type="button"], +#quota, +.pager li a { + width: 130px; + margin: 3px 3px 3px 0; + padding: 7px 6px 5px; + font-size: 13px; + background-color: #fff; + color: #333; + border: 1px solid #ddd; + outline: none; + border-radius: 3px; +} +input[type="hidden"] { + height: 0; + width: 0; +} +input[type="text"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="time"], +textarea { + background: #fff; + color: #555; + cursor: text; + font-family: inherit; /* use default ownCloud font instead of default textarea monospace */ +} +input[type="text"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="time"] { + -webkit-appearance:textfield; -moz-appearance:textfield; + -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; +} +input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active, +input[type="password"]:hover, input[type="password"]:focus, input[type="password"]:active, +input[type="number"]:hover, input[type="number"]:focus, input[type="number"]:active, +input[type="search"]:hover, input[type="search"]:focus, input[type="search"]:active, +input[type="email"]:hover, input[type="email"]:focus, input[type="email"]:active, +input[type="url"]:hover, input[type="url"]:focus, input[type="url"]:active, +input[type="time"]:hover, input[type="time"]:focus, input[type="time"]:active, +textarea:hover, textarea:focus, textarea:active { + color: #333; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + opacity: 1; +} + +.ie8 input[type="checkbox"] { margin:0; padding:0; height:auto; width:auto; } +.ie8 input[type="checkbox"]:hover+label, input[type="checkbox"]:focus+label { color:#111 !important; } + +/* ie8 doesn't support :checked */ +html:not(.ie8) input[type="checkbox"].checkbox { + position: absolute; + left:-10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; +} + +html:not(.ie8) input[type="checkbox"].checkbox + label:before { + content: ""; + display: inline-block; + + height: 20px; + width: 20px; + vertical-align: middle; + + background: url('../img/actions/checkbox.svg') left top no-repeat; + opacity: 0.7; +} + +html:not(.ie8) input[type="checkbox"].checkbox:disabled +label:before { opacity: .6; } + +html:not(.ie8) input[type="checkbox"].checkbox.u-left +label:before { float: left; } +html:not(.ie8) input[type="checkbox"].checkbox.u-hidden + label:before { display: none; } + +html:not(.ie8) input[type="checkbox"].checkbox--white + label:before { + background-image: url('../img/actions/checkbox-white.svg'); +} + +html:not(.ie8) input[type="checkbox"].checkbox:checked + label:before { + background-image: url('../img/actions/checkbox-checked.svg'); +} + +html:not(.ie8) input[type="checkbox"].checkbox--white:checked + label:before { + background-image: url('../img/actions/checkbox-checked-white.svg'); +} + +html:not(.ie8) input[type="checkbox"].checkbox:hover+label:before, input[type="checkbox"]:focus+label:before { + color:#111 !important; +} + +input[type="time"] { + width: initial; + height: 31px; + -moz-box-sizing: border-box; box-sizing: border-box; +} + +select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: url('../../core/img/actions/triangle-s.svg') no-repeat right 8px center rgba(240, 240, 240, 0.90); + outline: 0; + padding-right: 24px !important; +} + +select:hover { + background-color: #fefefe; +} + +.select2-choices { + border: 1px solid #ddd; + border-radius: 3px; + color: #333; + background-image: none; +} +.select2-dropdown-open .select2-choices { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border: 1px solid #3875d7; +} + +/* correctly align images inside of buttons */ +input img, button img, .button img { + vertical-align: text-bottom; +} + +input[type="submit"].enabled { + background-color: #66f866; + border: 1px solid #5e5; +} + +.input-button-inline { + position: absolute !important; + right: 0; + background-color: transparent !important; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; + opacity: .3; +} + + +/* BUTTONS */ +input[type="submit"], input[type="button"], +button, .button, +#quota, select, .pager li a { + width: auto; + min-width: 25px; + padding: 5px; + background-color: rgba(240,240,240,.9); + font-weight: 600; + color: #555; + border: 1px solid rgba(240,240,240,.9); + cursor: pointer; +} +select, .button.multiselect { + font-weight: 400; +} +input[type="submit"]:hover, input[type="submit"]:focus, +input[type="button"]:hover, input[type="button"]:focus, +button:hover, button:focus, +.button:hover, .button:focus, +.button a:focus, +select:hover, select:focus, select:active { + background-color: rgba(255, 255, 255, .95); + color: #111; +} +input[type="submit"] img, input[type="button"] img, button img, .button img { cursor:pointer; } +#header .button { + border: none; + box-shadow: none; +} + +/* disabled input fields and buttons */ +input:disabled, input:disabled:hover, input:disabled:focus, +button:disabled, button:disabled:hover, button:disabled:focus, +.button:disabled, .button:disabled:hover, .button:disabled:focus, +a.disabled, a.disabled:hover, a.disabled:focus, +textarea:disabled { + background-color: rgba(230,230,230,.9); + color: #999; + cursor: default; +} +input:disabled+label, input:disabled:hover+label, input:disabled:focus+label { + color: #999 !important; + cursor: default; +} + +/* Primary action button, use sparingly */ +.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary { + border: 1px solid #1d2d44; + background-color: #35537a; + color: #ddd; +} +.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover, +.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus { + background-color: #304d76; + color: #fff; +} +.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active, +.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled, +.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover, +.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus { + background-color: #1d2d44; + color: #bbb; +} diff --git a/core/css/styles.css b/core/css/styles.css index 066087cc433..c1638fe0a51 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -12,18 +12,6 @@ table, td, th { vertical-align:middle; } a { border:0; color:#000; text-decoration:none;} a, a *, input, input *, select, .button span, label { cursor:pointer; } ul { list-style:none; } -select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background: url('../../core/img/actions/triangle-s.svg') no-repeat right 8px center rgba(240, 240, 240, 0.90); - outline: 0; - padding-right: 24px !important; -} - -select:hover { - background-color: #fefefe; -} body { background-color: #ffffff; @@ -85,155 +73,6 @@ body { color: #ddd; } - - -/* INPUTS */ - -/* specifically override browser styles */ -input, textarea, select, button { - font-family: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif; -} - -input[type="text"], -input[type="password"], -input[type="search"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="time"], -input[type="date"], -textarea, -select, -button, .button, -input[type="submit"], -input[type="button"], -#quota, -.pager li a { - width: 130px; - margin: 3px 3px 3px 0; - padding: 7px 6px 5px; - font-size: 13px; - background-color: #fff; - color: #333; - border: 1px solid #ddd; - outline: none; - border-radius: 3px; -} -input[type="hidden"] { - height: 0; - width: 0; -} -input[type="text"], -input[type="password"], -input[type="search"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="time"], -textarea { - background: #fff; - color: #555; - cursor: text; - font-family: inherit; /* use default ownCloud font instead of default textarea monospace */ -} -input[type="text"], -input[type="password"], -input[type="search"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="time"] { - -webkit-appearance:textfield; -moz-appearance:textfield; - -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; -} -input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active, -input[type="password"]:hover, input[type="password"]:focus, input[type="password"]:active, -input[type="number"]:hover, input[type="number"]:focus, input[type="number"]:active, -.searchbox input[type="search"]:hover, .searchbox input[type="search"]:focus, .searchbox input[type="search"]:active, -input[type="email"]:hover, input[type="email"]:focus, input[type="email"]:active, -input[type="url"]:hover, input[type="url"]:focus, input[type="url"]:active, -input[type="time"]:hover, input[type="time"]:focus, input[type="time"]:active, -textarea:hover, textarea:focus, textarea:active { - color: #333; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - opacity: 1; -} - -.ie8 input[type="checkbox"] { margin:0; padding:0; height:auto; width:auto; } -.ie8 input[type="checkbox"]:hover+label, input[type="checkbox"]:focus+label { color:#111 !important; } - -/* ie8 doesn't support :checked */ -html:not(.ie8) input[type="checkbox"].checkbox { - position: absolute; - left:-10000px; - top: auto; - width: 1px; - height: 1px; - overflow: hidden; -} - -html:not(.ie8) input[type="checkbox"].checkbox + label:before { - content: ""; - display: inline-block; - - height: 20px; - width: 20px; - vertical-align: middle; - - background: url('../img/actions/checkbox.svg') left top no-repeat; - opacity: 0.7; -} - -html:not(.ie8) input[type="checkbox"].checkbox:disabled +label:before { opacity: .6; } - -html:not(.ie8) input[type="checkbox"].checkbox.u-left +label:before { float: left; } -html:not(.ie8) input[type="checkbox"].checkbox.u-hidden + label:before { display: none; } - -html:not(.ie8) input[type="checkbox"].checkbox--white + label:before { - background-image: url('../img/actions/checkbox-white.svg'); -} - -html:not(.ie8) input[type="checkbox"].checkbox:checked + label:before { - background-image: url('../img/actions/checkbox-checked.svg'); -} - -html:not(.ie8) input[type="checkbox"].checkbox--white:checked + label:before { - background-image: url('../img/actions/checkbox-checked-white.svg'); -} - -html:not(.ie8) input[type="checkbox"].checkbox:hover+label:before, input[type="checkbox"]:focus+label:before { - color:#111 !important; -} - -input[type="time"] { - width: initial; - height: 31px; - -moz-box-sizing: border-box; box-sizing: border-box; -} - -.select2-choices { - border: 1px solid #ddd; - border-radius: 3px; - color: #333; - background-image: none; -} -.select2-dropdown-open .select2-choices { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - border: 1px solid #3875d7; -} - -/* correctly align images inside of buttons */ -input img, button img, .button img { - vertical-align: text-bottom; -} - -#quota { - cursor: default; - margin: 30px; -} - - /* SCROLLING */ ::-webkit-scrollbar { width: 8px; @@ -245,72 +84,6 @@ input img, button img, .button img { background: #ddd; } - -/* BUTTONS */ -input[type="submit"], input[type="button"], -button, .button, -#quota, select, .pager li a { - width: auto; - min-width: 25px; - padding: 5px; - background-color: rgba(240,240,240,.9); - font-weight: 600; - color: #555; - border: 1px solid rgba(240,240,240,.9); - cursor: pointer; -} -select, .button.multiselect { - font-weight: 400; -} -input[type="submit"]:hover, input[type="submit"]:focus, -input[type="button"]:hover, input[type="button"]:focus, -button:hover, button:focus, -.button:hover, .button:focus, -.button a:focus, -select:hover, select:focus, select:active { - background-color: rgba(255, 255, 255, .95); - color: #111; -} -input[type="submit"] img, input[type="button"] img, button img, .button img { cursor:pointer; } -#header .button { - border: none; - box-shadow: none; -} - -/* disabled input fields and buttons */ -input:disabled, input:disabled:hover, input:disabled:focus, -button:disabled, button:disabled:hover, button:disabled:focus, -.button:disabled, .button:disabled:hover, .button:disabled:focus, -a.disabled, a.disabled:hover, a.disabled:focus, -textarea:disabled { - background-color: rgba(230,230,230,.9); - color: #999; - cursor: default; -} -input:disabled+label, input:disabled:hover+label, input:disabled:focus+label { - color: #999 !important; - cursor: default; -} - -/* Primary action button, use sparingly */ -.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary { - border: 1px solid #1d2d44; - background-color: #35537a; - color: #ddd; -} - .primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover, - .primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus { - background-color: #304d76; - color: #fff; - } - .primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active, - .primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled, - .primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover, - .primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus { - background-color: #1d2d44; - color: #bbb; - } - /* Searchbox */ .searchbox input[type="search"] { position: relative; @@ -342,21 +115,6 @@ input:disabled+label, input:disabled:hover+label, input:disabled:focus+label { background-color: #112; } -input[type="submit"].enabled { - background-color: #66f866; - border: 1px solid #5e5; -} - -.input-button-inline { - position: absolute !important; - right: 0; - background-color: transparent !important; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; - opacity: .3; -} - - - /* CONTENT ------------------------------------------------------------------ */ #controls { -moz-box-sizing: border-box; @@ -941,6 +699,8 @@ tbody tr:active { code { font-family:"Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", monospace; } #quota { + cursor: default; + margin: 30px; position: relative; padding: 0; } diff --git a/lib/private/template.php b/lib/private/template.php index 38527cdc461..bb30cfb8566 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -114,6 +114,7 @@ class OC_Template extends \OC\Template\Base { OC_Util::addStyle("icons",null,true); OC_Util::addStyle("mobile",null,true); OC_Util::addStyle("header",null,true); + OC_Util::addStyle("inputs",null,true); OC_Util::addStyle("styles",null,true); // avatars -- GitLab From 1e9203cdef7009ef129f0f3e3db6a326d3f4db12 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Fri, 13 Nov 2015 01:57:12 -0500 Subject: [PATCH 025/344] [tx-robot] updated from transifex --- apps/files/l10n/ar.js | 8 +++----- apps/files/l10n/ar.json | 8 +++----- apps/files/l10n/ast.js | 2 -- apps/files/l10n/ast.json | 2 -- apps/files/l10n/az.js | 8 +++----- apps/files/l10n/az.json | 8 +++----- apps/files/l10n/bg_BG.js | 5 ++--- apps/files/l10n/bg_BG.json | 5 ++--- apps/files/l10n/bn_BD.js | 2 +- apps/files/l10n/bn_BD.json | 2 +- apps/files/l10n/bs.js | 4 ++-- apps/files/l10n/bs.json | 4 ++-- apps/files/l10n/ca.js | 5 ++--- apps/files/l10n/ca.json | 5 ++--- apps/files/l10n/cs_CZ.js | 8 +++----- apps/files/l10n/cs_CZ.json | 8 +++----- apps/files/l10n/cy_GB.js | 2 +- apps/files/l10n/cy_GB.json | 2 +- apps/files/l10n/da.js | 2 -- apps/files/l10n/da.json | 2 -- apps/files/l10n/de.js | 8 +++----- apps/files/l10n/de.json | 8 +++----- apps/files/l10n/de_AT.js | 2 +- apps/files/l10n/de_AT.json | 2 +- apps/files/l10n/de_DE.js | 5 ++--- apps/files/l10n/de_DE.json | 5 ++--- apps/files/l10n/el.js | 2 -- apps/files/l10n/el.json | 2 -- apps/files/l10n/en_GB.js | 5 ++--- apps/files/l10n/en_GB.json | 5 ++--- apps/files/l10n/eo.js | 4 ++-- apps/files/l10n/eo.json | 4 ++-- apps/files/l10n/es.js | 8 +++----- apps/files/l10n/es.json | 8 +++----- apps/files/l10n/es_AR.js | 4 ++-- apps/files/l10n/es_AR.json | 4 ++-- apps/files/l10n/es_CL.js | 2 +- apps/files/l10n/es_CL.json | 2 +- apps/files/l10n/es_MX.js | 4 ++-- apps/files/l10n/es_MX.json | 4 ++-- apps/files/l10n/et_EE.js | 6 ++---- apps/files/l10n/et_EE.json | 6 ++---- apps/files/l10n/eu.js | 4 ++-- apps/files/l10n/eu.json | 4 ++-- apps/files/l10n/fa.js | 7 +++---- apps/files/l10n/fa.json | 7 +++---- apps/files/l10n/fi_FI.js | 8 +++----- apps/files/l10n/fi_FI.json | 8 +++----- apps/files/l10n/fr.js | 8 +++----- apps/files/l10n/fr.json | 8 +++----- apps/files/l10n/gl.js | 5 ++--- apps/files/l10n/gl.json | 5 ++--- apps/files/l10n/he.js | 2 +- apps/files/l10n/he.json | 2 +- apps/files/l10n/hi.js | 2 +- apps/files/l10n/hi.json | 2 +- apps/files/l10n/hr.js | 4 ++-- apps/files/l10n/hr.json | 4 ++-- apps/files/l10n/hu_HU.js | 8 +++----- apps/files/l10n/hu_HU.json | 8 +++----- apps/files/l10n/ia.js | 2 +- apps/files/l10n/ia.json | 2 +- apps/files/l10n/id.js | 8 +++----- apps/files/l10n/id.json | 8 +++----- apps/files/l10n/is.js | 2 +- apps/files/l10n/is.json | 2 +- apps/files/l10n/it.js | 8 +++----- apps/files/l10n/it.json | 8 +++----- apps/files/l10n/ja.js | 6 ++---- apps/files/l10n/ja.json | 6 ++---- apps/files/l10n/ka_GE.js | 2 +- apps/files/l10n/ka_GE.json | 2 +- apps/files/l10n/km.js | 2 +- apps/files/l10n/km.json | 2 +- apps/files/l10n/kn.js | 2 +- apps/files/l10n/kn.json | 2 +- apps/files/l10n/ko.js | 6 ++---- apps/files/l10n/ko.json | 6 ++---- apps/files/l10n/ku_IQ.js | 2 +- apps/files/l10n/ku_IQ.json | 2 +- apps/files/l10n/lb.js | 2 +- apps/files/l10n/lb.json | 2 +- apps/files/l10n/lt_LT.js | 2 -- apps/files/l10n/lt_LT.json | 2 -- apps/files/l10n/lv.js | 2 +- apps/files/l10n/lv.json | 2 +- apps/files/l10n/mk.js | 2 +- apps/files/l10n/mk.json | 2 +- apps/files/l10n/ms_MY.js | 2 +- apps/files/l10n/ms_MY.json | 2 +- apps/files/l10n/nb_NO.js | 6 ++---- apps/files/l10n/nb_NO.json | 6 ++---- apps/files/l10n/nl.js | 8 +++----- apps/files/l10n/nl.json | 8 +++----- apps/files/l10n/nn_NO.js | 4 ++-- apps/files/l10n/nn_NO.json | 4 ++-- apps/files/l10n/oc.js | 6 ++---- apps/files/l10n/oc.json | 6 ++---- apps/files/l10n/pl.js | 4 ++-- apps/files/l10n/pl.json | 4 ++-- apps/files/l10n/pt_BR.js | 8 +++----- apps/files/l10n/pt_BR.json | 8 +++----- apps/files/l10n/pt_PT.js | 2 -- apps/files/l10n/pt_PT.json | 2 -- apps/files/l10n/ro.js | 4 ++-- apps/files/l10n/ro.json | 4 ++-- apps/files/l10n/ru.js | 8 +++----- apps/files/l10n/ru.json | 8 +++----- apps/files/l10n/si_LK.js | 2 +- apps/files/l10n/si_LK.json | 2 +- apps/files/l10n/sk_SK.js | 8 +++----- apps/files/l10n/sk_SK.json | 8 +++----- apps/files/l10n/sl.js | 5 ++--- apps/files/l10n/sl.json | 5 ++--- apps/files/l10n/sq.js | 6 ++---- apps/files/l10n/sq.json | 6 ++---- apps/files/l10n/sr.js | 8 +++----- apps/files/l10n/sr.json | 8 +++----- apps/files/l10n/sr@latin.js | 5 ++--- apps/files/l10n/sr@latin.json | 5 ++--- apps/files/l10n/sv.js | 6 ++---- apps/files/l10n/sv.json | 6 ++---- apps/files/l10n/ta_IN.js | 2 +- apps/files/l10n/ta_IN.json | 2 +- apps/files/l10n/ta_LK.js | 2 +- apps/files/l10n/ta_LK.json | 2 +- apps/files/l10n/th_TH.js | 8 +++----- apps/files/l10n/th_TH.json | 8 +++----- apps/files/l10n/tr.js | 8 +++----- apps/files/l10n/tr.json | 8 +++----- apps/files/l10n/ug.js | 2 +- apps/files/l10n/ug.json | 2 +- apps/files/l10n/uk.js | 5 ++--- apps/files/l10n/uk.json | 5 ++--- apps/files/l10n/vi.js | 4 ++-- apps/files/l10n/vi.json | 4 ++-- apps/files/l10n/zh_CN.js | 8 +++----- apps/files/l10n/zh_CN.json | 8 +++----- apps/files/l10n/zh_HK.js | 2 +- apps/files/l10n/zh_HK.json | 2 +- apps/files/l10n/zh_TW.js | 2 -- apps/files/l10n/zh_TW.json | 2 -- apps/user_ldap/l10n/cs_CZ.js | 1 - apps/user_ldap/l10n/cs_CZ.json | 1 - apps/user_ldap/l10n/da.js | 1 - apps/user_ldap/l10n/da.json | 1 - apps/user_ldap/l10n/de.js | 1 - apps/user_ldap/l10n/de.json | 1 - apps/user_ldap/l10n/de_DE.js | 1 - apps/user_ldap/l10n/de_DE.json | 1 - apps/user_ldap/l10n/el.js | 1 - apps/user_ldap/l10n/el.json | 1 - apps/user_ldap/l10n/en_GB.js | 1 - apps/user_ldap/l10n/en_GB.json | 1 - apps/user_ldap/l10n/es.js | 1 - apps/user_ldap/l10n/es.json | 1 - apps/user_ldap/l10n/et_EE.js | 1 - apps/user_ldap/l10n/et_EE.json | 1 - apps/user_ldap/l10n/fr.js | 1 - apps/user_ldap/l10n/fr.json | 1 - apps/user_ldap/l10n/gl.js | 1 - apps/user_ldap/l10n/gl.json | 1 - apps/user_ldap/l10n/id.js | 1 - apps/user_ldap/l10n/id.json | 1 - apps/user_ldap/l10n/it.js | 1 - apps/user_ldap/l10n/it.json | 1 - apps/user_ldap/l10n/ja.js | 1 - apps/user_ldap/l10n/ja.json | 1 - apps/user_ldap/l10n/ko.js | 1 - apps/user_ldap/l10n/ko.json | 1 - apps/user_ldap/l10n/nb_NO.js | 1 - apps/user_ldap/l10n/nb_NO.json | 1 - apps/user_ldap/l10n/nl.js | 1 - apps/user_ldap/l10n/nl.json | 1 - apps/user_ldap/l10n/oc.js | 1 - apps/user_ldap/l10n/oc.json | 1 - apps/user_ldap/l10n/pt_BR.js | 1 - apps/user_ldap/l10n/pt_BR.json | 1 - apps/user_ldap/l10n/pt_PT.js | 1 - apps/user_ldap/l10n/pt_PT.json | 1 - apps/user_ldap/l10n/ru.js | 1 - apps/user_ldap/l10n/ru.json | 1 - apps/user_ldap/l10n/sk_SK.js | 1 - apps/user_ldap/l10n/sk_SK.json | 1 - apps/user_ldap/l10n/sl.js | 1 - apps/user_ldap/l10n/sl.json | 1 - apps/user_ldap/l10n/sq.js | 1 - apps/user_ldap/l10n/sq.json | 1 - apps/user_ldap/l10n/sr.js | 1 - apps/user_ldap/l10n/sr.json | 1 - apps/user_ldap/l10n/th_TH.js | 1 - apps/user_ldap/l10n/th_TH.json | 1 - apps/user_ldap/l10n/tr.js | 1 - apps/user_ldap/l10n/tr.json | 1 - apps/user_ldap/l10n/zh_TW.js | 1 - apps/user_ldap/l10n/zh_TW.json | 1 - core/l10n/af_ZA.js | 4 ++-- core/l10n/af_ZA.json | 4 ++-- core/l10n/ast.js | 1 - core/l10n/ast.json | 1 - core/l10n/az.js | 3 +-- core/l10n/az.json | 3 +-- core/l10n/bg_BG.js | 3 +-- core/l10n/bg_BG.json | 3 +-- core/l10n/bs.js | 3 +-- core/l10n/bs.json | 3 +-- core/l10n/ca.js | 3 +-- core/l10n/ca.json | 3 +-- core/l10n/cs_CZ.js | 1 - core/l10n/cs_CZ.json | 1 - core/l10n/da.js | 1 - core/l10n/da.json | 1 - core/l10n/de.js | 3 +-- core/l10n/de.json | 3 +-- core/l10n/de_DE.js | 3 +-- core/l10n/de_DE.json | 3 +-- core/l10n/el.js | 1 - core/l10n/el.json | 1 - core/l10n/en_GB.js | 3 +-- core/l10n/en_GB.json | 3 +-- core/l10n/es.js | 1 - core/l10n/es.json | 1 - core/l10n/es_CL.js | 3 +-- core/l10n/es_CL.json | 3 +-- core/l10n/et_EE.js | 3 +-- core/l10n/et_EE.json | 3 +-- core/l10n/eu.js | 3 +-- core/l10n/eu.json | 3 +-- core/l10n/fi_FI.js | 3 +-- core/l10n/fi_FI.json | 3 +-- core/l10n/fr.js | 1 - core/l10n/fr.json | 1 - core/l10n/gl.js | 3 +-- core/l10n/gl.json | 3 +-- core/l10n/hr.js | 3 +-- core/l10n/hr.json | 3 +-- core/l10n/hu_HU.js | 1 - core/l10n/hu_HU.json | 1 - core/l10n/id.js | 1 - core/l10n/id.json | 1 - core/l10n/is.js | 3 +-- core/l10n/is.json | 3 +-- core/l10n/it.js | 1 - core/l10n/it.json | 1 - core/l10n/ja.js | 1 - core/l10n/ja.json | 1 - core/l10n/ko.js | 1 - core/l10n/ko.json | 1 - core/l10n/nb_NO.js | 3 +-- core/l10n/nb_NO.json | 3 +-- core/l10n/nl.js | 1 - core/l10n/nl.json | 1 - core/l10n/oc.js | 3 +-- core/l10n/oc.json | 3 +-- core/l10n/pl.js | 3 +-- core/l10n/pl.json | 3 +-- core/l10n/pt_BR.js | 3 +-- core/l10n/pt_BR.json | 3 +-- core/l10n/pt_PT.js | 1 - core/l10n/pt_PT.json | 1 - core/l10n/ru.js | 3 +-- core/l10n/ru.json | 3 +-- core/l10n/sk_SK.js | 1 - core/l10n/sk_SK.json | 1 - core/l10n/sl.js | 3 +-- core/l10n/sl.json | 3 +-- core/l10n/sq.js | 3 +-- core/l10n/sq.json | 3 +-- core/l10n/sr.js | 3 +-- core/l10n/sr.json | 3 +-- core/l10n/sr@latin.js | 3 +-- core/l10n/sr@latin.json | 3 +-- core/l10n/sv.js | 3 +-- core/l10n/sv.json | 3 +-- core/l10n/th_TH.js | 1 - core/l10n/th_TH.json | 1 - core/l10n/tr.js | 1 - core/l10n/tr.json | 1 - core/l10n/uk.js | 3 +-- core/l10n/uk.json | 3 +-- core/l10n/zh_CN.js | 3 +-- core/l10n/zh_CN.json | 3 +-- core/l10n/zh_TW.js | 1 - core/l10n/zh_TW.json | 1 - 284 files changed, 312 insertions(+), 594 deletions(-) diff --git a/apps/files/l10n/ar.js b/apps/files/l10n/ar.js index 0e20f237022..b4414525c68 100644 --- a/apps/files/l10n/ar.js +++ b/apps/files/l10n/ar.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "المفضلة ", "Home" : "البيت", "Close" : "إغلاق", + "Upload cancelled." : "تم إلغاء عملية رفع الملفات .", "Unable to upload {filename} as it is a directory or has 0 bytes" : "تعذر رفع الملف {filename} إما لأنه مجلد أو لان حجم الملف 0 بايت", "Total file size {size1} exceeds upload limit {size2}" : "حجم الملف الكلي {size1} تجاوز الحد المسموح للرفع {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "لا يوجد مساحة تخزين كافية، انت تقوم برفع {size1} ولكن المساحه المتوفره هي {size2}.", - "Upload cancelled." : "تم إلغاء عملية رفع الملفات .", "Could not get result from server." : "تعذر الحصول على نتيجة من الخادم", "File upload is in progress. Leaving the page now will cancel the upload." : "عملية رفع الملفات قيد التنفيذ. اغلاق الصفحة سوف يلغي عملية رفع الملفات.", "Actions" : "* تطبيقات.\n* أنشطة.", @@ -70,12 +70,12 @@ OC.L10N.register( "Storage of {owner} is almost full ({usedSpacePercent}%)" : "المساحة التخزينية لـ {owner} ممتلئة تقريبا ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "مساحتك التخزينية امتلأت تقريبا ", "Favorite" : "المفضلة", - "{newname} already exists" : "{newname} موجود مسبقاً", - "Upload" : "رفع", "Text file" : "ملف نصي", "New text file.txt" : "ملف نصي جديد fille.txt", "Folder" : "مجلد", "New folder" : "مجلد جديد", + "{newname} already exists" : "{newname} موجود مسبقاً", + "Upload" : "رفع", "An error occurred while trying to update the tags" : "حدث خطأ اثناء محاولة تحديث tags", "A new file or folder has been created" : "تم إنشاء ملف جديد أو مجلد ", "A file or folder has been changed" : "تم تغيير ملف أو مجلد", @@ -96,9 +96,7 @@ OC.L10N.register( "File handling" : "التعامل مع الملف", "Maximum upload size" : "الحد الأقصى لحجم الملفات التي يمكن رفعها", "max. possible: " : "الحد الأقصى المسموح به", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "بستخدام PHP-FPM هذه القيمة سوف تحتاج الي 5 دقائق حتي تُتِم عملها بعد الحفظ ", "Save" : "حفظ", - "Can not be edited from here due to insufficient permissions." : "لا يمكن التعديل من هنا نظرا لعدم توفر الصلاحيات الكافيه ", "Settings" : "إعدادات", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "استخدم هذا العنوان لـ الدخول الى ملفاتك عن طريق WebDAV", diff --git a/apps/files/l10n/ar.json b/apps/files/l10n/ar.json index e1b2eb3af1b..0783c769ee1 100644 --- a/apps/files/l10n/ar.json +++ b/apps/files/l10n/ar.json @@ -28,10 +28,10 @@ "Favorites" : "المفضلة ", "Home" : "البيت", "Close" : "إغلاق", + "Upload cancelled." : "تم إلغاء عملية رفع الملفات .", "Unable to upload {filename} as it is a directory or has 0 bytes" : "تعذر رفع الملف {filename} إما لأنه مجلد أو لان حجم الملف 0 بايت", "Total file size {size1} exceeds upload limit {size2}" : "حجم الملف الكلي {size1} تجاوز الحد المسموح للرفع {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "لا يوجد مساحة تخزين كافية، انت تقوم برفع {size1} ولكن المساحه المتوفره هي {size2}.", - "Upload cancelled." : "تم إلغاء عملية رفع الملفات .", "Could not get result from server." : "تعذر الحصول على نتيجة من الخادم", "File upload is in progress. Leaving the page now will cancel the upload." : "عملية رفع الملفات قيد التنفيذ. اغلاق الصفحة سوف يلغي عملية رفع الملفات.", "Actions" : "* تطبيقات.\n* أنشطة.", @@ -68,12 +68,12 @@ "Storage of {owner} is almost full ({usedSpacePercent}%)" : "المساحة التخزينية لـ {owner} ممتلئة تقريبا ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "مساحتك التخزينية امتلأت تقريبا ", "Favorite" : "المفضلة", - "{newname} already exists" : "{newname} موجود مسبقاً", - "Upload" : "رفع", "Text file" : "ملف نصي", "New text file.txt" : "ملف نصي جديد fille.txt", "Folder" : "مجلد", "New folder" : "مجلد جديد", + "{newname} already exists" : "{newname} موجود مسبقاً", + "Upload" : "رفع", "An error occurred while trying to update the tags" : "حدث خطأ اثناء محاولة تحديث tags", "A new file or folder has been created" : "تم إنشاء ملف جديد أو مجلد ", "A file or folder has been changed" : "تم تغيير ملف أو مجلد", @@ -94,9 +94,7 @@ "File handling" : "التعامل مع الملف", "Maximum upload size" : "الحد الأقصى لحجم الملفات التي يمكن رفعها", "max. possible: " : "الحد الأقصى المسموح به", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "بستخدام PHP-FPM هذه القيمة سوف تحتاج الي 5 دقائق حتي تُتِم عملها بعد الحفظ ", "Save" : "حفظ", - "Can not be edited from here due to insufficient permissions." : "لا يمكن التعديل من هنا نظرا لعدم توفر الصلاحيات الكافيه ", "Settings" : "إعدادات", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "استخدم هذا العنوان لـ الدخول الى ملفاتك عن طريق WebDAV", diff --git a/apps/files/l10n/ast.js b/apps/files/l10n/ast.js index 926587837dd..5dfcae172ea 100644 --- a/apps/files/l10n/ast.js +++ b/apps/files/l10n/ast.js @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Alministración de ficheros", "Maximum upload size" : "Tamañu máximu de xubida", "max. possible: " : "máx. posible:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Con PHP-FPM esti valor pue retrasase 5 minutos pa tener efeutu dempués de salvar.", "Save" : "Guardar", - "Can not be edited from here due to insufficient permissions." : "Nun pue editáse dende equí por mor d'insuficientes permisos.", "Settings" : "Axustes", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Usa esta direición p'acceder a los ficheros a traviés de WebDAV", diff --git a/apps/files/l10n/ast.json b/apps/files/l10n/ast.json index 750ed1f959a..a0934808529 100644 --- a/apps/files/l10n/ast.json +++ b/apps/files/l10n/ast.json @@ -103,9 +103,7 @@ "File handling" : "Alministración de ficheros", "Maximum upload size" : "Tamañu máximu de xubida", "max. possible: " : "máx. posible:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Con PHP-FPM esti valor pue retrasase 5 minutos pa tener efeutu dempués de salvar.", "Save" : "Guardar", - "Can not be edited from here due to insufficient permissions." : "Nun pue editáse dende equí por mor d'insuficientes permisos.", "Settings" : "Axustes", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Usa esta direición p'acceder a los ficheros a traviés de WebDAV", diff --git a/apps/files/l10n/az.js b/apps/files/l10n/az.js index b278fad62b1..10cbd661ebf 100644 --- a/apps/files/l10n/az.js +++ b/apps/files/l10n/az.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Sevimlilər", "Home" : "Ev", "Close" : "Bağla", + "Upload cancelled." : "Yüklənmə dayandırıldı.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Yükləmək olmur {filename} ona görə ki, ya qovluqdur yada ki, həcmi 0 baytdır ", "Total file size {size1} exceeds upload limit {size2}" : "Ümumi fayl həcmi {size1} yüklənmə limiti {size2} -ni aşır", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Kifayət qədər boş yer yoxdur, siz yükləyirsiniz {size1} ancaq {size2} var. ", - "Upload cancelled." : "Yüklənmə dayandırıldı.", "Could not get result from server." : "Nəticəni serverdən almaq mümkün olmur.", "File upload is in progress. Leaving the page now will cancel the upload." : "Faylın yüklənməsi gedir. Əgər səhifəni indi tərk etsəniz yüklənmə dayanacaq.", "Actions" : "İşlər", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n baytlar","%n bytes"], "Favorited" : "İstəkləndi", "Favorite" : "İstəkli", - "{newname} already exists" : "{newname} artıq mövcuddur", - "Upload" : "Serverə yüklə", "Text file" : "Tekst faylı", "New text file.txt" : "Yeni mətn file.txt", "Folder" : "Qovluq", "New folder" : "Yeni qovluq", + "{newname} already exists" : "{newname} artıq mövcuddur", + "Upload" : "Serverə yüklə", "An error occurred while trying to update the tags" : "Qeydlərin yenilənməsi müddətində səhv baş verdi ", "A new file or folder has been created" : "Yeni fayl və ya direktoriya yaradılmışdır", "A file or folder has been changed" : "Fayl və ya direktoriya dəyişdirilib", @@ -102,9 +102,7 @@ OC.L10N.register( "File handling" : "Fayl emalı", "Maximum upload size" : "Maksimal yükləmə həcmi", "max. possible: " : "maks. ola bilər: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM ilə bu məna yadda saxladıldıqından 5 dəqiqə sonra işə düşə bilər. ", "Save" : "Saxlamaq", - "Can not be edited from here due to insufficient permissions." : "Yetki çatışmamazlığına görə, burdan başlayaraq dəyişiklik edə bilməzsiniz.", "Settings" : "Quraşdırmalar", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Bu ünvanı WebDAV vasitəsilə fayllarınızı əldə etmək üçün istifadə edə bilərsiniz. ", diff --git a/apps/files/l10n/az.json b/apps/files/l10n/az.json index 8603939790d..0587f91d97b 100644 --- a/apps/files/l10n/az.json +++ b/apps/files/l10n/az.json @@ -28,10 +28,10 @@ "Favorites" : "Sevimlilər", "Home" : "Ev", "Close" : "Bağla", + "Upload cancelled." : "Yüklənmə dayandırıldı.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Yükləmək olmur {filename} ona görə ki, ya qovluqdur yada ki, həcmi 0 baytdır ", "Total file size {size1} exceeds upload limit {size2}" : "Ümumi fayl həcmi {size1} yüklənmə limiti {size2} -ni aşır", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Kifayət qədər boş yer yoxdur, siz yükləyirsiniz {size1} ancaq {size2} var. ", - "Upload cancelled." : "Yüklənmə dayandırıldı.", "Could not get result from server." : "Nəticəni serverdən almaq mümkün olmur.", "File upload is in progress. Leaving the page now will cancel the upload." : "Faylın yüklənməsi gedir. Əgər səhifəni indi tərk etsəniz yüklənmə dayanacaq.", "Actions" : "İşlər", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n baytlar","%n bytes"], "Favorited" : "İstəkləndi", "Favorite" : "İstəkli", - "{newname} already exists" : "{newname} artıq mövcuddur", - "Upload" : "Serverə yüklə", "Text file" : "Tekst faylı", "New text file.txt" : "Yeni mətn file.txt", "Folder" : "Qovluq", "New folder" : "Yeni qovluq", + "{newname} already exists" : "{newname} artıq mövcuddur", + "Upload" : "Serverə yüklə", "An error occurred while trying to update the tags" : "Qeydlərin yenilənməsi müddətində səhv baş verdi ", "A new file or folder has been created" : "Yeni fayl və ya direktoriya yaradılmışdır", "A file or folder has been changed" : "Fayl və ya direktoriya dəyişdirilib", @@ -100,9 +100,7 @@ "File handling" : "Fayl emalı", "Maximum upload size" : "Maksimal yükləmə həcmi", "max. possible: " : "maks. ola bilər: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM ilə bu məna yadda saxladıldıqından 5 dəqiqə sonra işə düşə bilər. ", "Save" : "Saxlamaq", - "Can not be edited from here due to insufficient permissions." : "Yetki çatışmamazlığına görə, burdan başlayaraq dəyişiklik edə bilməzsiniz.", "Settings" : "Quraşdırmalar", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Bu ünvanı WebDAV vasitəsilə fayllarınızı əldə etmək üçün istifadə edə bilərsiniz. ", diff --git a/apps/files/l10n/bg_BG.js b/apps/files/l10n/bg_BG.js index 98e0e2bd4b9..7f83daa45f6 100644 --- a/apps/files/l10n/bg_BG.js +++ b/apps/files/l10n/bg_BG.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Любими", "Home" : "Домашен", "Close" : "Затвори", + "Upload cancelled." : "Качването е прекъснато.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Неуспешно качване на {filename}, защото е директория или е с размер от 0 байта.", "Total file size {size1} exceeds upload limit {size2}" : "Общия размер {size1} надминава лимита за качване {size2}.", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Няма достатъчно свободно място, ти се опитваш да качиш {size1}, но са останали само {size2}.", - "Upload cancelled." : "Качването е прекъснато.", "Could not get result from server." : "Не се получи резултат от сървърът.", "File upload is in progress. Leaving the page now will cancel the upload." : "Извършва се качване на файлове. Затварянето на тази страница ще прекъсне качването.", "Actions" : "Действия", @@ -69,10 +69,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["пасва на '{filter}'","пасват на '{filter}'\n "], "Favorited" : "Отбелязано в любими", "Favorite" : "Любими", - "Upload" : "Качване", "Text file" : "Текстов файл", "Folder" : "Папка", "New folder" : "Нова папка", + "Upload" : "Качване", "An error occurred while trying to update the tags" : "Настъпи грешка при опита за промяна на бележките", "A new file or folder has been created" : "Нов файл или папка беше създаден/а", "A file or folder has been changed" : "Файл или папка беше променен/а", @@ -94,7 +94,6 @@ OC.L10N.register( "Maximum upload size" : "Максимален размер", "max. possible: " : "максимално:", "Save" : "Запис", - "Can not be edited from here due to insufficient permissions." : "Не може да бъде редактиран от тук, поради липса на права", "Settings" : "Настройки", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Използвай този адрес, за да получиш достъп до своите файлове чрез WebDAV.", diff --git a/apps/files/l10n/bg_BG.json b/apps/files/l10n/bg_BG.json index 48d6729232b..639b39c258d 100644 --- a/apps/files/l10n/bg_BG.json +++ b/apps/files/l10n/bg_BG.json @@ -28,10 +28,10 @@ "Favorites" : "Любими", "Home" : "Домашен", "Close" : "Затвори", + "Upload cancelled." : "Качването е прекъснато.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Неуспешно качване на {filename}, защото е директория или е с размер от 0 байта.", "Total file size {size1} exceeds upload limit {size2}" : "Общия размер {size1} надминава лимита за качване {size2}.", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Няма достатъчно свободно място, ти се опитваш да качиш {size1}, но са останали само {size2}.", - "Upload cancelled." : "Качването е прекъснато.", "Could not get result from server." : "Не се получи резултат от сървърът.", "File upload is in progress. Leaving the page now will cancel the upload." : "Извършва се качване на файлове. Затварянето на тази страница ще прекъсне качването.", "Actions" : "Действия", @@ -67,10 +67,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["пасва на '{filter}'","пасват на '{filter}'\n "], "Favorited" : "Отбелязано в любими", "Favorite" : "Любими", - "Upload" : "Качване", "Text file" : "Текстов файл", "Folder" : "Папка", "New folder" : "Нова папка", + "Upload" : "Качване", "An error occurred while trying to update the tags" : "Настъпи грешка при опита за промяна на бележките", "A new file or folder has been created" : "Нов файл или папка беше създаден/а", "A file or folder has been changed" : "Файл или папка беше променен/а", @@ -92,7 +92,6 @@ "Maximum upload size" : "Максимален размер", "max. possible: " : "максимално:", "Save" : "Запис", - "Can not be edited from here due to insufficient permissions." : "Не може да бъде редактиран от тук, поради липса на права", "Settings" : "Настройки", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Използвай този адрес, за да получиш достъп до своите файлове чрез WebDAV.", diff --git a/apps/files/l10n/bn_BD.js b/apps/files/l10n/bn_BD.js index bc8d7ce8d5c..412f4aa0399 100644 --- a/apps/files/l10n/bn_BD.js +++ b/apps/files/l10n/bn_BD.js @@ -47,10 +47,10 @@ OC.L10N.register( "File name cannot be empty." : "ফাইলের নামটি ফাঁকা রাখা যাবে না।", "Your storage is almost full ({usedSpacePercent}%)" : "আপনার সংরক্ষণাধার প্রায় পরিপূর্ণ ({usedSpacePercent}%) ", "Favorite" : "প্রিয়জন", - "Upload" : "আপলোড", "Text file" : "টেক্সট ফাইল", "Folder" : "ফোল্ডার", "New folder" : "নব ফােলডার", + "Upload" : "আপলোড", "A new file or folder has been created" : "একটি ফাইল বা ফোলডার তৈরি করা হয়েছে", "A file or folder has been changed" : "একটি ফাইল বা ফোলডার পরিবরতন করা হয়েছে", "A file or folder has been deleted" : "একটি ফাইল বা ফোলডার মোছা হয়েছে", diff --git a/apps/files/l10n/bn_BD.json b/apps/files/l10n/bn_BD.json index 43ebbc8ad96..b8078f43071 100644 --- a/apps/files/l10n/bn_BD.json +++ b/apps/files/l10n/bn_BD.json @@ -45,10 +45,10 @@ "File name cannot be empty." : "ফাইলের নামটি ফাঁকা রাখা যাবে না।", "Your storage is almost full ({usedSpacePercent}%)" : "আপনার সংরক্ষণাধার প্রায় পরিপূর্ণ ({usedSpacePercent}%) ", "Favorite" : "প্রিয়জন", - "Upload" : "আপলোড", "Text file" : "টেক্সট ফাইল", "Folder" : "ফোল্ডার", "New folder" : "নব ফােলডার", + "Upload" : "আপলোড", "A new file or folder has been created" : "একটি ফাইল বা ফোলডার তৈরি করা হয়েছে", "A file or folder has been changed" : "একটি ফাইল বা ফোলডার পরিবরতন করা হয়েছে", "A file or folder has been deleted" : "একটি ফাইল বা ফোলডার মোছা হয়েছে", diff --git a/apps/files/l10n/bs.js b/apps/files/l10n/bs.js index 6ca6ebe90c5..b084f2eb3be 100644 --- a/apps/files/l10n/bs.js +++ b/apps/files/l10n/bs.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoriti", "Home" : "Kuća", "Close" : "Zatvori", + "Upload cancelled." : "Učitavanje je prekinuto.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nemoguće učitati {filename} jer je ili direktorij ili ima 0 bajta", "Total file size {size1} exceeds upload limit {size2}" : "Ukupna veličina datoteke {size1} prelazi ograničenje unosa {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nedovoljno slobodnog prostora, vi učitavate {size1} a samo je {size2} preostalo", - "Upload cancelled." : "Učitavanje je prekinuto.", "Could not get result from server." : "Nemoguće dobiti rezultat od servera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Učitavanje datoteke je u toku. Napuštanje stranice prekinut će učitavanje.", "Actions" : "Radnje", @@ -66,10 +66,10 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Vaš prostor za pohranu je skoro pun ({usedSpacePercent}%)", "Favorited" : "Favorizovano", "Favorite" : "Favorit", - "Upload" : "Učitaj", "Text file" : "Tekstualna datoteka", "Folder" : "Direktorij", "New folder" : "Novi direktorij", + "Upload" : "Učitaj", "%s could not be renamed as it has been deleted" : "%s nije moguće preimenovati jer je izbrisan", "%s could not be renamed" : "%s nije moguće preimenovati", "Upload (max. %s)" : "Učitaj (max. %s)", diff --git a/apps/files/l10n/bs.json b/apps/files/l10n/bs.json index 553662622f2..e02689ff9fe 100644 --- a/apps/files/l10n/bs.json +++ b/apps/files/l10n/bs.json @@ -28,10 +28,10 @@ "Favorites" : "Favoriti", "Home" : "Kuća", "Close" : "Zatvori", + "Upload cancelled." : "Učitavanje je prekinuto.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nemoguće učitati {filename} jer je ili direktorij ili ima 0 bajta", "Total file size {size1} exceeds upload limit {size2}" : "Ukupna veličina datoteke {size1} prelazi ograničenje unosa {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nedovoljno slobodnog prostora, vi učitavate {size1} a samo je {size2} preostalo", - "Upload cancelled." : "Učitavanje je prekinuto.", "Could not get result from server." : "Nemoguće dobiti rezultat od servera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Učitavanje datoteke je u toku. Napuštanje stranice prekinut će učitavanje.", "Actions" : "Radnje", @@ -64,10 +64,10 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Vaš prostor za pohranu je skoro pun ({usedSpacePercent}%)", "Favorited" : "Favorizovano", "Favorite" : "Favorit", - "Upload" : "Učitaj", "Text file" : "Tekstualna datoteka", "Folder" : "Direktorij", "New folder" : "Novi direktorij", + "Upload" : "Učitaj", "%s could not be renamed as it has been deleted" : "%s nije moguće preimenovati jer je izbrisan", "%s could not be renamed" : "%s nije moguće preimenovati", "Upload (max. %s)" : "Učitaj (max. %s)", diff --git a/apps/files/l10n/ca.js b/apps/files/l10n/ca.js index b5cd0beedfe..601781a1182 100644 --- a/apps/files/l10n/ca.js +++ b/apps/files/l10n/ca.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Preferits", "Home" : "Casa", "Close" : "Tanca", + "Upload cancelled." : "La pujada s'ha cancel·lat.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "No es pot pujar {filename} perquè és una carpeta o té 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "Mida total del fitxer {size1} excedeix el límit de pujada {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "No hi ha prou espai lliure, està carregant {size1} però només pot {size2}", - "Upload cancelled." : "La pujada s'ha cancel·lat.", "Could not get result from server." : "No hi ha resposta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "Hi ha una pujada en curs. Si abandoneu la pàgina la pujada es cancel·larà.", "Actions" : "Accions", @@ -71,10 +71,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["coincidències '{filter}'","coincidència '{filter}'"], "Favorited" : "Agregat a favorits", "Favorite" : "Preferits", - "Upload" : "Puja", "Text file" : "Fitxer de text", "Folder" : "Carpeta", "New folder" : "Carpeta nova", + "Upload" : "Puja", "An error occurred while trying to update the tags" : "S'ha produït un error en tractar d'actualitzar les etiquetes", "A new file or folder has been created" : "S'ha creat un nou fitxer o una nova carpeta", "A file or folder has been changed" : "S'ha canviat un fitxer o una carpeta", @@ -97,7 +97,6 @@ OC.L10N.register( "Maximum upload size" : "Mida màxima de pujada", "max. possible: " : "màxim possible:", "Save" : "Desa", - "Can not be edited from here due to insufficient permissions." : "No es pot editar des d'aquí per permisos insuficients.", "Settings" : "Arranjament", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Useu aquesta adreça per accedir als fitxers via WebDAV", diff --git a/apps/files/l10n/ca.json b/apps/files/l10n/ca.json index 7558821627f..748a55d3c8e 100644 --- a/apps/files/l10n/ca.json +++ b/apps/files/l10n/ca.json @@ -28,10 +28,10 @@ "Favorites" : "Preferits", "Home" : "Casa", "Close" : "Tanca", + "Upload cancelled." : "La pujada s'ha cancel·lat.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "No es pot pujar {filename} perquè és una carpeta o té 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "Mida total del fitxer {size1} excedeix el límit de pujada {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "No hi ha prou espai lliure, està carregant {size1} però només pot {size2}", - "Upload cancelled." : "La pujada s'ha cancel·lat.", "Could not get result from server." : "No hi ha resposta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "Hi ha una pujada en curs. Si abandoneu la pàgina la pujada es cancel·larà.", "Actions" : "Accions", @@ -69,10 +69,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["coincidències '{filter}'","coincidència '{filter}'"], "Favorited" : "Agregat a favorits", "Favorite" : "Preferits", - "Upload" : "Puja", "Text file" : "Fitxer de text", "Folder" : "Carpeta", "New folder" : "Carpeta nova", + "Upload" : "Puja", "An error occurred while trying to update the tags" : "S'ha produït un error en tractar d'actualitzar les etiquetes", "A new file or folder has been created" : "S'ha creat un nou fitxer o una nova carpeta", "A file or folder has been changed" : "S'ha canviat un fitxer o una carpeta", @@ -95,7 +95,6 @@ "Maximum upload size" : "Mida màxima de pujada", "max. possible: " : "màxim possible:", "Save" : "Desa", - "Can not be edited from here due to insufficient permissions." : "No es pot editar des d'aquí per permisos insuficients.", "Settings" : "Arranjament", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Useu aquesta adreça per accedir als fitxers via WebDAV", diff --git a/apps/files/l10n/cs_CZ.js b/apps/files/l10n/cs_CZ.js index 10f9d49984f..f93b1f5d7a1 100644 --- a/apps/files/l10n/cs_CZ.js +++ b/apps/files/l10n/cs_CZ.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Oblíbené", "Home" : "Domů", "Close" : "Zavřít", + "Upload cancelled." : "Odesílání zrušeno.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nelze nahrát soubor {filename}, protože je to buď adresář nebo má velikost 0 bytů", "Total file size {size1} exceeds upload limit {size2}" : "Celková velikost souboru {size1} překračuje povolenou velikost pro nahrávání {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Není dostatek místa pro uložení, velikost souboru je {size1}, zbývá pouze {size2}", - "Upload cancelled." : "Odesílání zrušeno.", "Could not get result from server." : "Nepodařilo se získat výsledek ze serveru.", "File upload is in progress. Leaving the page now will cancel the upload." : "Probíhá odesílání souboru. Opuštění stránky způsobí zrušení nahrávání.", "Actions" : "Činnosti", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n bajt","%n bajty","%n bajtů"], "Favorited" : "Přidáno k oblíbeným", "Favorite" : "Oblíbené", - "{newname} already exists" : "{newname} již existuje", - "Upload" : "Odeslat", "Text file" : "Textový soubor", "New text file.txt" : "Nový textový soubor.txt", "Folder" : "Složka", "New folder" : "Nová složka", + "{newname} already exists" : "{newname} již existuje", + "Upload" : "Odeslat", "An error occurred while trying to update the tags" : "Při pokusu o úpravu tagů nastala chyba", "A new file or folder has been created" : "Byl vytvořen nový soubor nebo složka", "A file or folder has been changed" : "Soubor nebo složka byla změněna", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Zacházení se soubory", "Maximum upload size" : "Maximální velikost pro odesílání", "max. possible: " : "největší možná: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Při použití PHP-FPM může změna tohoto nastavení trvat až 5 minut po jeho uložení.", "Save" : "Uložit", - "Can not be edited from here due to insufficient permissions." : "Nelze odsud upravovat z důvodu nedostatečných oprávnění.", "Settings" : "Nastavení", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Použijte tuto adresu pro přístup k vašim souborům přes WebDAV", diff --git a/apps/files/l10n/cs_CZ.json b/apps/files/l10n/cs_CZ.json index cc475fbfd5c..7daf7a492da 100644 --- a/apps/files/l10n/cs_CZ.json +++ b/apps/files/l10n/cs_CZ.json @@ -28,10 +28,10 @@ "Favorites" : "Oblíbené", "Home" : "Domů", "Close" : "Zavřít", + "Upload cancelled." : "Odesílání zrušeno.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nelze nahrát soubor {filename}, protože je to buď adresář nebo má velikost 0 bytů", "Total file size {size1} exceeds upload limit {size2}" : "Celková velikost souboru {size1} překračuje povolenou velikost pro nahrávání {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Není dostatek místa pro uložení, velikost souboru je {size1}, zbývá pouze {size2}", - "Upload cancelled." : "Odesílání zrušeno.", "Could not get result from server." : "Nepodařilo se získat výsledek ze serveru.", "File upload is in progress. Leaving the page now will cancel the upload." : "Probíhá odesílání souboru. Opuštění stránky způsobí zrušení nahrávání.", "Actions" : "Činnosti", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n bajt","%n bajty","%n bajtů"], "Favorited" : "Přidáno k oblíbeným", "Favorite" : "Oblíbené", - "{newname} already exists" : "{newname} již existuje", - "Upload" : "Odeslat", "Text file" : "Textový soubor", "New text file.txt" : "Nový textový soubor.txt", "Folder" : "Složka", "New folder" : "Nová složka", + "{newname} already exists" : "{newname} již existuje", + "Upload" : "Odeslat", "An error occurred while trying to update the tags" : "Při pokusu o úpravu tagů nastala chyba", "A new file or folder has been created" : "Byl vytvořen nový soubor nebo složka", "A file or folder has been changed" : "Soubor nebo složka byla změněna", @@ -103,9 +103,7 @@ "File handling" : "Zacházení se soubory", "Maximum upload size" : "Maximální velikost pro odesílání", "max. possible: " : "největší možná: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Při použití PHP-FPM může změna tohoto nastavení trvat až 5 minut po jeho uložení.", "Save" : "Uložit", - "Can not be edited from here due to insufficient permissions." : "Nelze odsud upravovat z důvodu nedostatečných oprávnění.", "Settings" : "Nastavení", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Použijte tuto adresu pro přístup k vašim souborům přes WebDAV", diff --git a/apps/files/l10n/cy_GB.js b/apps/files/l10n/cy_GB.js index 2f64d032f01..570fc14fa3a 100644 --- a/apps/files/l10n/cy_GB.js +++ b/apps/files/l10n/cy_GB.js @@ -33,9 +33,9 @@ OC.L10N.register( "File name cannot be empty." : "Does dim hawl cael enw ffeil gwag.", "Your storage is full, files can not be updated or synced anymore!" : "Mae eich storfa'n llawn, ni ellir diweddaru a chydweddu ffeiliau mwyach!", "Your storage is almost full ({usedSpacePercent}%)" : "Mae eich storfa bron a bod yn llawn ({usedSpacePercent}%)", - "Upload" : "Llwytho i fyny", "Text file" : "Ffeil destun", "Folder" : "Plygell", + "Upload" : "Llwytho i fyny", "File handling" : "Trafod ffeiliau", "Maximum upload size" : "Maint mwyaf llwytho i fyny", "max. possible: " : "mwyaf. posib:", diff --git a/apps/files/l10n/cy_GB.json b/apps/files/l10n/cy_GB.json index 602cc780abe..e0b42d77a7a 100644 --- a/apps/files/l10n/cy_GB.json +++ b/apps/files/l10n/cy_GB.json @@ -31,9 +31,9 @@ "File name cannot be empty." : "Does dim hawl cael enw ffeil gwag.", "Your storage is full, files can not be updated or synced anymore!" : "Mae eich storfa'n llawn, ni ellir diweddaru a chydweddu ffeiliau mwyach!", "Your storage is almost full ({usedSpacePercent}%)" : "Mae eich storfa bron a bod yn llawn ({usedSpacePercent}%)", - "Upload" : "Llwytho i fyny", "Text file" : "Ffeil destun", "Folder" : "Plygell", + "Upload" : "Llwytho i fyny", "File handling" : "Trafod ffeiliau", "Maximum upload size" : "Maint mwyaf llwytho i fyny", "max. possible: " : "mwyaf. posib:", diff --git a/apps/files/l10n/da.js b/apps/files/l10n/da.js index 4f8cd7ab497..307a58e74f0 100644 --- a/apps/files/l10n/da.js +++ b/apps/files/l10n/da.js @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Filhåndtering", "Maximum upload size" : "Maksimal upload-størrelse", "max. possible: " : "max. mulige: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Med denne PHP-FPM værdi, kan der gå op til 5 minutter før virkningen indtræffer, efter at der gemmes.", "Save" : "Gem", - "Can not be edited from here due to insufficient permissions." : "Kan ikke redigeres herfra på grund af utilstrækkelige rettigheder.", "Settings" : "Indstillinger", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Brug denne adresse for at tilgå dine filer via WebDAV", diff --git a/apps/files/l10n/da.json b/apps/files/l10n/da.json index d0fe2575d3e..ae5d9655536 100644 --- a/apps/files/l10n/da.json +++ b/apps/files/l10n/da.json @@ -103,9 +103,7 @@ "File handling" : "Filhåndtering", "Maximum upload size" : "Maksimal upload-størrelse", "max. possible: " : "max. mulige: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Med denne PHP-FPM værdi, kan der gå op til 5 minutter før virkningen indtræffer, efter at der gemmes.", "Save" : "Gem", - "Can not be edited from here due to insufficient permissions." : "Kan ikke redigeres herfra på grund af utilstrækkelige rettigheder.", "Settings" : "Indstillinger", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Brug denne adresse for at tilgå dine filer via WebDAV", diff --git a/apps/files/l10n/de.js b/apps/files/l10n/de.js index b6f3711617a..5a35a5f21ee 100644 --- a/apps/files/l10n/de.js +++ b/apps/files/l10n/de.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoriten", "Home" : "Home", "Close" : "Schließen", + "Upload cancelled." : "Upload abgebrochen.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist", "Total file size {size1} exceeds upload limit {size2}" : "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nicht genügend freier Speicherplatz, du möchtest {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.", - "Upload cancelled." : "Upload abgebrochen.", "Could not get result from server." : "Ergebnis konnte nicht vom Server abgerufen werden.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dateiupload läuft. Wenn Du die Seite jetzt verlässt, wird der Upload abgebrochen.", "Actions" : "Aktionen", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"], "Favorited" : "Favorisiert", "Favorite" : "Favorit", - "{newname} already exists" : "{newname} existiert bereits", - "Upload" : "Hochladen", "Text file" : "Textdatei", "New text file.txt" : "Neue Textdatei.txt", "Folder" : "Ordner", "New folder" : "Neuer Ordner", + "{newname} already exists" : "{newname} existiert bereits", + "Upload" : "Hochladen", "An error occurred while trying to update the tags" : "Es ist ein Fehler beim Aktualisieren der Tags aufgetreten", "A new file or folder has been created" : "Eine neue Datei oder ein neuer Ordner wurde erstellt", "A file or folder has been changed" : "Eine Datei oder ein Ordner wurde geändert", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Dateibehandlung", "Maximum upload size" : "Maximale Upload-Größe", "max. possible: " : "maximal möglich:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Mit PHP-FPM kann es bis zu 5 Minuten dauern, bis die Einstellungen übernommen werden.", "Save" : "Speichern", - "Can not be edited from here due to insufficient permissions." : "Aufgrund unzureichender Berechtigungen kann dies nicht von hier bearbeitet werden.", "Settings" : "Einstellungen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Benutze diese Adresse, um über WebDAV auf Deine Dateien zuzugreifen", diff --git a/apps/files/l10n/de.json b/apps/files/l10n/de.json index d0cfab4929e..860a97916be 100644 --- a/apps/files/l10n/de.json +++ b/apps/files/l10n/de.json @@ -28,10 +28,10 @@ "Favorites" : "Favoriten", "Home" : "Home", "Close" : "Schließen", + "Upload cancelled." : "Upload abgebrochen.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist", "Total file size {size1} exceeds upload limit {size2}" : "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nicht genügend freier Speicherplatz, du möchtest {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.", - "Upload cancelled." : "Upload abgebrochen.", "Could not get result from server." : "Ergebnis konnte nicht vom Server abgerufen werden.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dateiupload läuft. Wenn Du die Seite jetzt verlässt, wird der Upload abgebrochen.", "Actions" : "Aktionen", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"], "Favorited" : "Favorisiert", "Favorite" : "Favorit", - "{newname} already exists" : "{newname} existiert bereits", - "Upload" : "Hochladen", "Text file" : "Textdatei", "New text file.txt" : "Neue Textdatei.txt", "Folder" : "Ordner", "New folder" : "Neuer Ordner", + "{newname} already exists" : "{newname} existiert bereits", + "Upload" : "Hochladen", "An error occurred while trying to update the tags" : "Es ist ein Fehler beim Aktualisieren der Tags aufgetreten", "A new file or folder has been created" : "Eine neue Datei oder ein neuer Ordner wurde erstellt", "A file or folder has been changed" : "Eine Datei oder ein Ordner wurde geändert", @@ -103,9 +103,7 @@ "File handling" : "Dateibehandlung", "Maximum upload size" : "Maximale Upload-Größe", "max. possible: " : "maximal möglich:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Mit PHP-FPM kann es bis zu 5 Minuten dauern, bis die Einstellungen übernommen werden.", "Save" : "Speichern", - "Can not be edited from here due to insufficient permissions." : "Aufgrund unzureichender Berechtigungen kann dies nicht von hier bearbeitet werden.", "Settings" : "Einstellungen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Benutze diese Adresse, um über WebDAV auf Deine Dateien zuzugreifen", diff --git a/apps/files/l10n/de_AT.js b/apps/files/l10n/de_AT.js index 4f5296dc11f..7bebb1e6eaf 100644 --- a/apps/files/l10n/de_AT.js +++ b/apps/files/l10n/de_AT.js @@ -7,8 +7,8 @@ OC.L10N.register( "Delete" : "Löschen", "Details" : "Details", "Error" : "Fehler", - "Upload" : "Hochladen", "New folder" : "Neuer Ordner", + "Upload" : "Hochladen", "A new file or folder has been created" : "Eine neue Datei oder ein neuer Ordner wurde erstellt", "A file or folder has been changed" : "Eine Datei oder ein Ordner hat sich geändert", "A file or folder has been deleted" : "Eine Datei oder ein Ordner wurde gelöscht", diff --git a/apps/files/l10n/de_AT.json b/apps/files/l10n/de_AT.json index 91ec7e5e4e1..fffb3863e85 100644 --- a/apps/files/l10n/de_AT.json +++ b/apps/files/l10n/de_AT.json @@ -5,8 +5,8 @@ "Delete" : "Löschen", "Details" : "Details", "Error" : "Fehler", - "Upload" : "Hochladen", "New folder" : "Neuer Ordner", + "Upload" : "Hochladen", "A new file or folder has been created" : "Eine neue Datei oder ein neuer Ordner wurde erstellt", "A file or folder has been changed" : "Eine Datei oder ein Ordner hat sich geändert", "A file or folder has been deleted" : "Eine Datei oder ein Ordner wurde gelöscht", diff --git a/apps/files/l10n/de_DE.js b/apps/files/l10n/de_DE.js index 9a75b417ace..ddb84ffedfb 100644 --- a/apps/files/l10n/de_DE.js +++ b/apps/files/l10n/de_DE.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoriten", "Home" : "Zuhause", "Close" : "Schließen", + "Upload cancelled." : "Upload abgebrochen.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist", "Total file size {size1} exceeds upload limit {size2}" : "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nicht genügend freier Speicherplatz, Sie möchten {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.", - "Upload cancelled." : "Upload abgebrochen.", "Could not get result from server." : "Ergebnis konnte nicht vom Server abgerufen werden.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen.", "Actions" : "Aktionen", @@ -73,10 +73,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["stimmt mit '{filter}' überein","stimmen mit '{filter}' überein"], "Favorited" : "Favorisiert", "Favorite" : "Favorit", - "Upload" : "Hochladen", "Text file" : "Textdatei", "Folder" : "Ordner", "New folder" : "Neuer Ordner", + "Upload" : "Hochladen", "An error occurred while trying to update the tags" : "Es ist ein Fehler beim Aktualisieren der Tags aufgetreten", "A new file or folder has been created" : "Eine neue Datei oder ein neuer Ordner wurde erstellt", "A file or folder has been changed" : "Eine Datei oder ein Ordner wurde geändert", @@ -99,7 +99,6 @@ OC.L10N.register( "Maximum upload size" : "Maximale Upload-Größe", "max. possible: " : "maximal möglich:", "Save" : "Speichern", - "Can not be edited from here due to insufficient permissions." : "Aufgrund unzureichender Berechtigungen kann dies nicht von hier bearbeitet werden.", "Settings" : "Einstellungen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Benutzen Sie diese Adresse, um über WebDAV auf Ihre Dateien zuzugreifen", diff --git a/apps/files/l10n/de_DE.json b/apps/files/l10n/de_DE.json index 910ad9ac6aa..5f7cd053e8e 100644 --- a/apps/files/l10n/de_DE.json +++ b/apps/files/l10n/de_DE.json @@ -28,10 +28,10 @@ "Favorites" : "Favoriten", "Home" : "Zuhause", "Close" : "Schließen", + "Upload cancelled." : "Upload abgebrochen.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist", "Total file size {size1} exceeds upload limit {size2}" : "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nicht genügend freier Speicherplatz, Sie möchten {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.", - "Upload cancelled." : "Upload abgebrochen.", "Could not get result from server." : "Ergebnis konnte nicht vom Server abgerufen werden.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen.", "Actions" : "Aktionen", @@ -71,10 +71,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["stimmt mit '{filter}' überein","stimmen mit '{filter}' überein"], "Favorited" : "Favorisiert", "Favorite" : "Favorit", - "Upload" : "Hochladen", "Text file" : "Textdatei", "Folder" : "Ordner", "New folder" : "Neuer Ordner", + "Upload" : "Hochladen", "An error occurred while trying to update the tags" : "Es ist ein Fehler beim Aktualisieren der Tags aufgetreten", "A new file or folder has been created" : "Eine neue Datei oder ein neuer Ordner wurde erstellt", "A file or folder has been changed" : "Eine Datei oder ein Ordner wurde geändert", @@ -97,7 +97,6 @@ "Maximum upload size" : "Maximale Upload-Größe", "max. possible: " : "maximal möglich:", "Save" : "Speichern", - "Can not be edited from here due to insufficient permissions." : "Aufgrund unzureichender Berechtigungen kann dies nicht von hier bearbeitet werden.", "Settings" : "Einstellungen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Benutzen Sie diese Adresse, um über WebDAV auf Ihre Dateien zuzugreifen", diff --git a/apps/files/l10n/el.js b/apps/files/l10n/el.js index 113f10266a4..36066e9fe9c 100644 --- a/apps/files/l10n/el.js +++ b/apps/files/l10n/el.js @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Διαχείριση αρχείων", "Maximum upload size" : "Μέγιστο μέγεθος αποστολής", "max. possible: " : "μέγιστο δυνατό:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Με την PHP-FPM αυτή η τιμή μπορεί να χρειαστεί μέχρι και 5 λεπτά για να ενεργοποιηθεί μετά την αποθήκευση.", "Save" : "Αποθήκευση", - "Can not be edited from here due to insufficient permissions." : "Δεν είναι δυνατή η επεξεργασία λόγω μη επαρκών δικαιωμάτων", "Settings" : "Ρυθμίσεις", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε πρόσβαση στα αρχεία σας μέσω WebDAV", diff --git a/apps/files/l10n/el.json b/apps/files/l10n/el.json index baaea21511c..7f0ce4dfe38 100644 --- a/apps/files/l10n/el.json +++ b/apps/files/l10n/el.json @@ -103,9 +103,7 @@ "File handling" : "Διαχείριση αρχείων", "Maximum upload size" : "Μέγιστο μέγεθος αποστολής", "max. possible: " : "μέγιστο δυνατό:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Με την PHP-FPM αυτή η τιμή μπορεί να χρειαστεί μέχρι και 5 λεπτά για να ενεργοποιηθεί μετά την αποθήκευση.", "Save" : "Αποθήκευση", - "Can not be edited from here due to insufficient permissions." : "Δεν είναι δυνατή η επεξεργασία λόγω μη επαρκών δικαιωμάτων", "Settings" : "Ρυθμίσεις", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε πρόσβαση στα αρχεία σας μέσω WebDAV", diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js index 5109eb0743b..cf37ac56dc0 100644 --- a/apps/files/l10n/en_GB.js +++ b/apps/files/l10n/en_GB.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favourites", "Home" : "Home", "Close" : "Close", + "Upload cancelled." : "Upload cancelled.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Unable to upload {filename} as it is a directory or has 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "Total file size {size1} exceeds upload limit {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Not enough free space, you are uploading {size1} but only {size2} is left", - "Upload cancelled." : "Upload cancelled.", "Could not get result from server." : "Could not get result from server.", "File upload is in progress. Leaving the page now will cancel the upload." : "File upload is in progress. Leaving the page now will cancel the upload.", "Actions" : "Actions", @@ -69,10 +69,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "Favorited" : "Favourited", "Favorite" : "Favourite", - "Upload" : "Upload", "Text file" : "Text file", "Folder" : "Folder", "New folder" : "New folder", + "Upload" : "Upload", "An error occurred while trying to update the tags" : "An error occurred whilst trying to update the tags", "A new file or folder has been created" : "A new file or folder has been created", "A file or folder has been changed" : "A file or folder has been changed", @@ -95,7 +95,6 @@ OC.L10N.register( "Maximum upload size" : "Maximum upload size", "max. possible: " : "max. possible: ", "Save" : "Save", - "Can not be edited from here due to insufficient permissions." : "Can not be edited from here due to insufficient permissions.", "Settings" : "Settings", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use this address to access your Files via WebDAV", diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json index 1f9acabeda3..764198384a6 100644 --- a/apps/files/l10n/en_GB.json +++ b/apps/files/l10n/en_GB.json @@ -28,10 +28,10 @@ "Favorites" : "Favourites", "Home" : "Home", "Close" : "Close", + "Upload cancelled." : "Upload cancelled.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Unable to upload {filename} as it is a directory or has 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "Total file size {size1} exceeds upload limit {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Not enough free space, you are uploading {size1} but only {size2} is left", - "Upload cancelled." : "Upload cancelled.", "Could not get result from server." : "Could not get result from server.", "File upload is in progress. Leaving the page now will cancel the upload." : "File upload is in progress. Leaving the page now will cancel the upload.", "Actions" : "Actions", @@ -67,10 +67,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "Favorited" : "Favourited", "Favorite" : "Favourite", - "Upload" : "Upload", "Text file" : "Text file", "Folder" : "Folder", "New folder" : "New folder", + "Upload" : "Upload", "An error occurred while trying to update the tags" : "An error occurred whilst trying to update the tags", "A new file or folder has been created" : "A new file or folder has been created", "A file or folder has been changed" : "A file or folder has been changed", @@ -93,7 +93,6 @@ "Maximum upload size" : "Maximum upload size", "max. possible: " : "max. possible: ", "Save" : "Save", - "Can not be edited from here due to insufficient permissions." : "Can not be edited from here due to insufficient permissions.", "Settings" : "Settings", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use this address to access your Files via WebDAV", diff --git a/apps/files/l10n/eo.js b/apps/files/l10n/eo.js index b881c3d9d01..eb8ffd7728b 100644 --- a/apps/files/l10n/eo.js +++ b/apps/files/l10n/eo.js @@ -25,8 +25,8 @@ OC.L10N.register( "Favorites" : "Favoratoj", "Home" : "Hejmo", "Close" : "Fermi", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ne povis alŝutiĝi {filename} ĉar ĝi estas dosierujo aŭ ĝi havas 0 duumokojn", "Upload cancelled." : "La alŝuto nuliĝis.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ne povis alŝutiĝi {filename} ĉar ĝi estas dosierujo aŭ ĝi havas 0 duumokojn", "Could not get result from server." : "Ne povis ekhaviĝi rezulto el la servilo.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dosieralŝuto plenumiĝas. Lasi la paĝon nun nuligus la alŝuton.", "Actions" : "Agoj", @@ -55,10 +55,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "Via memoro plenas, ne plu eblas ĝisdatigi aŭ sinkronigi dosierojn!", "Your storage is almost full ({usedSpacePercent}%)" : "Via memoro preskaŭ plenas ({usedSpacePercent}%)", "Favorite" : "Favorato", - "Upload" : "Alŝuti", "Text file" : "Tekstodosiero", "Folder" : "Dosierujo", "New folder" : "Nova dosierujo", + "Upload" : "Alŝuti", "You created %1$s" : "Vi kreis %1$s", "%2$s created %1$s" : "%2$s kreis %1$s", "%1$s was created in a public folder" : "%1$s kreiĝis en publika dosierujo", diff --git a/apps/files/l10n/eo.json b/apps/files/l10n/eo.json index 93f3bdbede1..5f899df1e0c 100644 --- a/apps/files/l10n/eo.json +++ b/apps/files/l10n/eo.json @@ -23,8 +23,8 @@ "Favorites" : "Favoratoj", "Home" : "Hejmo", "Close" : "Fermi", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ne povis alŝutiĝi {filename} ĉar ĝi estas dosierujo aŭ ĝi havas 0 duumokojn", "Upload cancelled." : "La alŝuto nuliĝis.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ne povis alŝutiĝi {filename} ĉar ĝi estas dosierujo aŭ ĝi havas 0 duumokojn", "Could not get result from server." : "Ne povis ekhaviĝi rezulto el la servilo.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dosieralŝuto plenumiĝas. Lasi la paĝon nun nuligus la alŝuton.", "Actions" : "Agoj", @@ -53,10 +53,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "Via memoro plenas, ne plu eblas ĝisdatigi aŭ sinkronigi dosierojn!", "Your storage is almost full ({usedSpacePercent}%)" : "Via memoro preskaŭ plenas ({usedSpacePercent}%)", "Favorite" : "Favorato", - "Upload" : "Alŝuti", "Text file" : "Tekstodosiero", "Folder" : "Dosierujo", "New folder" : "Nova dosierujo", + "Upload" : "Alŝuti", "You created %1$s" : "Vi kreis %1$s", "%2$s created %1$s" : "%2$s kreis %1$s", "%1$s was created in a public folder" : "%1$s kreiĝis en publika dosierujo", diff --git a/apps/files/l10n/es.js b/apps/files/l10n/es.js index 15062395e40..5226fb4774e 100644 --- a/apps/files/l10n/es.js +++ b/apps/files/l10n/es.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Particular", "Close" : "Cerrar", + "Upload cancelled." : "Subida cancelada.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "El tamaño total del archivo {size1} excede el límite {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "No hay suficiente espacio libre. Quiere subir {size1} pero solo quedan {size2}", - "Upload cancelled." : "Subida cancelada.", "Could not get result from server." : "No se pudo obtener respuesta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La subida del archivo está en proceso. Si sale de la página ahora, la subida será cancelada.", "Actions" : "Acciones", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Agregado a Favoritos", "Favorite" : "Favorito", - "{newname} already exists" : "{new_name} ya existe", - "Upload" : "Subir", "Text file" : "Archivo de texto", "New text file.txt" : "Nuevo archivo de texto.txt", "Folder" : "Carpeta", "New folder" : "Nueva carpeta", + "{newname} already exists" : "{new_name} ya existe", + "Upload" : "Subir", "An error occurred while trying to update the tags" : "Se produjo un error al tratar de actualizar las etiquetas", "A new file or folder has been created" : "Se ha creado un nuevo archivo o carpeta", "A file or folder has been changed" : "Se ha modificado un archivo o carpeta", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Administración de archivos", "Maximum upload size" : "Tamaño máximo de subida", "max. possible: " : "máx. posible:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Con PHP-FPM este valor se puede demorar hasta 5 minutos para tener efecto después de guardar.", "Save" : "Guardar", - "Can not be edited from here due to insufficient permissions." : "No se puede editar desde aquí por permisos insuficientes.", "Settings" : "Ajustes", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use esta URL para acceder via WebDAV", diff --git a/apps/files/l10n/es.json b/apps/files/l10n/es.json index 4ce106ea4b5..cb255204571 100644 --- a/apps/files/l10n/es.json +++ b/apps/files/l10n/es.json @@ -28,10 +28,10 @@ "Favorites" : "Favoritos", "Home" : "Particular", "Close" : "Cerrar", + "Upload cancelled." : "Subida cancelada.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "El tamaño total del archivo {size1} excede el límite {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "No hay suficiente espacio libre. Quiere subir {size1} pero solo quedan {size2}", - "Upload cancelled." : "Subida cancelada.", "Could not get result from server." : "No se pudo obtener respuesta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La subida del archivo está en proceso. Si sale de la página ahora, la subida será cancelada.", "Actions" : "Acciones", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Agregado a Favoritos", "Favorite" : "Favorito", - "{newname} already exists" : "{new_name} ya existe", - "Upload" : "Subir", "Text file" : "Archivo de texto", "New text file.txt" : "Nuevo archivo de texto.txt", "Folder" : "Carpeta", "New folder" : "Nueva carpeta", + "{newname} already exists" : "{new_name} ya existe", + "Upload" : "Subir", "An error occurred while trying to update the tags" : "Se produjo un error al tratar de actualizar las etiquetas", "A new file or folder has been created" : "Se ha creado un nuevo archivo o carpeta", "A file or folder has been changed" : "Se ha modificado un archivo o carpeta", @@ -103,9 +103,7 @@ "File handling" : "Administración de archivos", "Maximum upload size" : "Tamaño máximo de subida", "max. possible: " : "máx. posible:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Con PHP-FPM este valor se puede demorar hasta 5 minutos para tener efecto después de guardar.", "Save" : "Guardar", - "Can not be edited from here due to insufficient permissions." : "No se puede editar desde aquí por permisos insuficientes.", "Settings" : "Ajustes", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use esta URL para acceder via WebDAV", diff --git a/apps/files/l10n/es_AR.js b/apps/files/l10n/es_AR.js index f81f0e6bed1..4f74717175d 100644 --- a/apps/files/l10n/es_AR.js +++ b/apps/files/l10n/es_AR.js @@ -25,8 +25,8 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Particular", "Close" : "Cerrar", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "Imposible cargar {filename} puesto que es un directoro o tiene 0 bytes.", "Upload cancelled." : "La subida fue cancelada", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "Imposible cargar {filename} puesto que es un directoro o tiene 0 bytes.", "Could not get result from server." : "No se pudo obtener resultados del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La subida del archivo está en proceso. Si salís de la página ahora, la subida se cancelará.", "Actions" : "Acciones", @@ -56,10 +56,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "El almacenamiento está lleno, los archivos no se pueden seguir actualizando ni sincronizando", "Your storage is almost full ({usedSpacePercent}%)" : "El almacenamiento está casi lleno ({usedSpacePercent}%)", "Favorite" : "Favorito", - "Upload" : "Subir", "Text file" : "Archivo de texto", "Folder" : "Carpeta", "New folder" : "Nueva Carpeta", + "Upload" : "Subir", "A new file or folder has been created" : "Un archivo o carpeta ha sido creado", "A file or folder has been changed" : "Un archivo o carpeta ha sido modificado", "A file or folder has been deleted" : "Un archivo o carpeta ha sido eliminado", diff --git a/apps/files/l10n/es_AR.json b/apps/files/l10n/es_AR.json index a9d5c8ece30..363fedc787e 100644 --- a/apps/files/l10n/es_AR.json +++ b/apps/files/l10n/es_AR.json @@ -23,8 +23,8 @@ "Favorites" : "Favoritos", "Home" : "Particular", "Close" : "Cerrar", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "Imposible cargar {filename} puesto que es un directoro o tiene 0 bytes.", "Upload cancelled." : "La subida fue cancelada", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "Imposible cargar {filename} puesto que es un directoro o tiene 0 bytes.", "Could not get result from server." : "No se pudo obtener resultados del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La subida del archivo está en proceso. Si salís de la página ahora, la subida se cancelará.", "Actions" : "Acciones", @@ -54,10 +54,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "El almacenamiento está lleno, los archivos no se pueden seguir actualizando ni sincronizando", "Your storage is almost full ({usedSpacePercent}%)" : "El almacenamiento está casi lleno ({usedSpacePercent}%)", "Favorite" : "Favorito", - "Upload" : "Subir", "Text file" : "Archivo de texto", "Folder" : "Carpeta", "New folder" : "Nueva Carpeta", + "Upload" : "Subir", "A new file or folder has been created" : "Un archivo o carpeta ha sido creado", "A file or folder has been changed" : "Un archivo o carpeta ha sido modificado", "A file or folder has been deleted" : "Un archivo o carpeta ha sido eliminado", diff --git a/apps/files/l10n/es_CL.js b/apps/files/l10n/es_CL.js index 9b0929f50af..f7443bc4944 100644 --- a/apps/files/l10n/es_CL.js +++ b/apps/files/l10n/es_CL.js @@ -7,8 +7,8 @@ OC.L10N.register( "Rename" : "Renombrar", "Details" : "detalles", "Error" : "Error", - "Upload" : "Subir", "New folder" : "Nuevo directorio", + "Upload" : "Subir", "A new file or folder has been created" : "Un nuevo archivo o carpeta ha sido creado", "A file or folder has been changed" : "Un archivo o carpeta ha sido cambiado", "A file or folder has been deleted" : "Un archivo o carpeta ha sido eliminado", diff --git a/apps/files/l10n/es_CL.json b/apps/files/l10n/es_CL.json index 57c23a61ea7..29c0ef45fcf 100644 --- a/apps/files/l10n/es_CL.json +++ b/apps/files/l10n/es_CL.json @@ -5,8 +5,8 @@ "Rename" : "Renombrar", "Details" : "detalles", "Error" : "Error", - "Upload" : "Subir", "New folder" : "Nuevo directorio", + "Upload" : "Subir", "A new file or folder has been created" : "Un nuevo archivo o carpeta ha sido creado", "A file or folder has been changed" : "Un archivo o carpeta ha sido cambiado", "A file or folder has been deleted" : "Un archivo o carpeta ha sido eliminado", diff --git a/apps/files/l10n/es_MX.js b/apps/files/l10n/es_MX.js index 5502733d2e2..dadcf54d15c 100644 --- a/apps/files/l10n/es_MX.js +++ b/apps/files/l10n/es_MX.js @@ -25,8 +25,8 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Particular", "Close" : "Cerrar", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", "Upload cancelled." : "Subida cancelada.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", "Could not get result from server." : "No se pudo obtener respuesta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La subida del archivo está en proceso. Si sale de la página ahora, la subida será cancelada.", "Actions" : "Acciones", @@ -55,10 +55,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!", "Your storage is almost full ({usedSpacePercent}%)" : "Su almacenamiento está casi lleno ({usedSpacePercent}%)", "Favorite" : "Favorito", - "Upload" : "Subir archivo", "Text file" : "Archivo de texto", "Folder" : "Carpeta", "New folder" : "Nueva carpeta", + "Upload" : "Subir archivo", "You created %1$s" : "Has creado %1$s", "You changed %1$s" : "Has cambiado %1$s", "You deleted %1$s" : "Has eliminado %1$s", diff --git a/apps/files/l10n/es_MX.json b/apps/files/l10n/es_MX.json index 22918fae182..61156506368 100644 --- a/apps/files/l10n/es_MX.json +++ b/apps/files/l10n/es_MX.json @@ -23,8 +23,8 @@ "Favorites" : "Favoritos", "Home" : "Particular", "Close" : "Cerrar", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", "Upload cancelled." : "Subida cancelada.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", "Could not get result from server." : "No se pudo obtener respuesta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La subida del archivo está en proceso. Si sale de la página ahora, la subida será cancelada.", "Actions" : "Acciones", @@ -53,10 +53,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!", "Your storage is almost full ({usedSpacePercent}%)" : "Su almacenamiento está casi lleno ({usedSpacePercent}%)", "Favorite" : "Favorito", - "Upload" : "Subir archivo", "Text file" : "Archivo de texto", "Folder" : "Carpeta", "New folder" : "Nueva carpeta", + "Upload" : "Subir archivo", "You created %1$s" : "Has creado %1$s", "You changed %1$s" : "Has cambiado %1$s", "You deleted %1$s" : "Has eliminado %1$s", diff --git a/apps/files/l10n/et_EE.js b/apps/files/l10n/et_EE.js index 86bda48300b..e57e6e39c81 100644 --- a/apps/files/l10n/et_EE.js +++ b/apps/files/l10n/et_EE.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Lemmikud", "Home" : "Kodu", "Close" : "Sulge", + "Upload cancelled." : "Üleslaadimine tühistati.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ei saa üles laadida {filename}, kuna see on kataloog või selle suurus on 0 baiti", "Total file size {size1} exceeds upload limit {size2}" : "Faili suurus {size1} ületab faili üleslaadimise mahu piirangu {size2}.", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Pole piisavalt vaba ruumi. Sa laadid üles {size1}, kuid ainult {size2} on saadaval.", - "Upload cancelled." : "Üleslaadimine tühistati.", "Could not get result from server." : "Serverist ei saadud tulemusi", "File upload is in progress. Leaving the page now will cancel the upload." : "Faili üleslaadimine on töös. Lehelt lahkumine katkestab selle üleslaadimise.", "Actions" : "Tegevused", @@ -74,10 +74,10 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n bait","%n baiti"], "Favorited" : "Lemmikud", "Favorite" : "Lemmik", - "Upload" : "Lae üles", "Text file" : "Tekstifail", "Folder" : "Kaust", "New folder" : "Uus kaust", + "Upload" : "Lae üles", "An error occurred while trying to update the tags" : "Siltide uuendamisel tekkis tõrge", "A new file or folder has been created" : "Uus fail või kataloog on loodud", "A file or folder has been changed" : "Fail või kataloog on muudetud", @@ -98,9 +98,7 @@ OC.L10N.register( "File handling" : "Failide käsitlemine", "Maximum upload size" : "Maksimaalne üleslaadimise suurus", "max. possible: " : "maks. võimalik: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM-ga võib see väärtuse mõju rakendamine võtta aega kuni 5 minutit pärast salvestamist.", "Save" : "Salvesta", - "Can not be edited from here due to insufficient permissions." : "Ei saa õiguste puudumise tõttu muuta.", "Settings" : "Seaded", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Kasuta seda aadressi oma failidele ligipääsuks WebDAV kaudu", diff --git a/apps/files/l10n/et_EE.json b/apps/files/l10n/et_EE.json index a95de6cf039..02dc68f96d9 100644 --- a/apps/files/l10n/et_EE.json +++ b/apps/files/l10n/et_EE.json @@ -28,10 +28,10 @@ "Favorites" : "Lemmikud", "Home" : "Kodu", "Close" : "Sulge", + "Upload cancelled." : "Üleslaadimine tühistati.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ei saa üles laadida {filename}, kuna see on kataloog või selle suurus on 0 baiti", "Total file size {size1} exceeds upload limit {size2}" : "Faili suurus {size1} ületab faili üleslaadimise mahu piirangu {size2}.", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Pole piisavalt vaba ruumi. Sa laadid üles {size1}, kuid ainult {size2} on saadaval.", - "Upload cancelled." : "Üleslaadimine tühistati.", "Could not get result from server." : "Serverist ei saadud tulemusi", "File upload is in progress. Leaving the page now will cancel the upload." : "Faili üleslaadimine on töös. Lehelt lahkumine katkestab selle üleslaadimise.", "Actions" : "Tegevused", @@ -72,10 +72,10 @@ "_%n byte_::_%n bytes_" : ["%n bait","%n baiti"], "Favorited" : "Lemmikud", "Favorite" : "Lemmik", - "Upload" : "Lae üles", "Text file" : "Tekstifail", "Folder" : "Kaust", "New folder" : "Uus kaust", + "Upload" : "Lae üles", "An error occurred while trying to update the tags" : "Siltide uuendamisel tekkis tõrge", "A new file or folder has been created" : "Uus fail või kataloog on loodud", "A file or folder has been changed" : "Fail või kataloog on muudetud", @@ -96,9 +96,7 @@ "File handling" : "Failide käsitlemine", "Maximum upload size" : "Maksimaalne üleslaadimise suurus", "max. possible: " : "maks. võimalik: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM-ga võib see väärtuse mõju rakendamine võtta aega kuni 5 minutit pärast salvestamist.", "Save" : "Salvesta", - "Can not be edited from here due to insufficient permissions." : "Ei saa õiguste puudumise tõttu muuta.", "Settings" : "Seaded", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Kasuta seda aadressi oma failidele ligipääsuks WebDAV kaudu", diff --git a/apps/files/l10n/eu.js b/apps/files/l10n/eu.js index c01afc96c55..0758119cad4 100644 --- a/apps/files/l10n/eu.js +++ b/apps/files/l10n/eu.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Gogokoak", "Home" : "Etxekoa", "Close" : "Itxi", + "Upload cancelled." : "Igoera ezeztatuta", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ezin da {filename} igo karpeta bat delako edo 0 byte dituelako", "Total file size {size1} exceeds upload limit {size2}" : "Fitxategiaren tamainak {size1} igotzeko muga {size2} gainditzen du", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ez dago leku nahikorik, zu {size1} igotzen ari zara baina bakarrik {size2} libre dago", - "Upload cancelled." : "Igoera ezeztatuta", "Could not get result from server." : "Ezin da zerbitzaritik emaitzik lortu", "File upload is in progress. Leaving the page now will cancel the upload." : "Fitxategien igoera martxan da. Orria orain uzteak igoera ezeztatutko du.", "Actions" : "Ekintzak", @@ -68,10 +68,10 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Zure biltegiratzea nahiko beterik dago (%{usedSpacePercent})", "Favorited" : "Gogokoa", "Favorite" : "Gogokoa", - "Upload" : "Igo", "Text file" : "Testu fitxategia", "Folder" : "Karpeta", "New folder" : "Karpeta berria", + "Upload" : "Igo", "A new file or folder has been created" : "Fitxategi edo karpeta berri bat sortu da", "A file or folder has been changed" : "Fitxategi edo karpeta bat aldatu da", "A file or folder has been deleted" : "Fitxategi edo karpeta bat ezabatu da", diff --git a/apps/files/l10n/eu.json b/apps/files/l10n/eu.json index 997e8bf73cf..9e225f2290a 100644 --- a/apps/files/l10n/eu.json +++ b/apps/files/l10n/eu.json @@ -28,10 +28,10 @@ "Favorites" : "Gogokoak", "Home" : "Etxekoa", "Close" : "Itxi", + "Upload cancelled." : "Igoera ezeztatuta", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ezin da {filename} igo karpeta bat delako edo 0 byte dituelako", "Total file size {size1} exceeds upload limit {size2}" : "Fitxategiaren tamainak {size1} igotzeko muga {size2} gainditzen du", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ez dago leku nahikorik, zu {size1} igotzen ari zara baina bakarrik {size2} libre dago", - "Upload cancelled." : "Igoera ezeztatuta", "Could not get result from server." : "Ezin da zerbitzaritik emaitzik lortu", "File upload is in progress. Leaving the page now will cancel the upload." : "Fitxategien igoera martxan da. Orria orain uzteak igoera ezeztatutko du.", "Actions" : "Ekintzak", @@ -66,10 +66,10 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Zure biltegiratzea nahiko beterik dago (%{usedSpacePercent})", "Favorited" : "Gogokoa", "Favorite" : "Gogokoa", - "Upload" : "Igo", "Text file" : "Testu fitxategia", "Folder" : "Karpeta", "New folder" : "Karpeta berria", + "Upload" : "Igo", "A new file or folder has been created" : "Fitxategi edo karpeta berri bat sortu da", "A file or folder has been changed" : "Fitxategi edo karpeta bat aldatu da", "A file or folder has been deleted" : "Fitxategi edo karpeta bat ezabatu da", diff --git a/apps/files/l10n/fa.js b/apps/files/l10n/fa.js index b053d4af79b..306992d15af 100644 --- a/apps/files/l10n/fa.js +++ b/apps/files/l10n/fa.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "موارد محبوب", "Home" : "خانه", "Close" : "بستن", + "Upload cancelled." : "بار گذاری لغو شد", "Unable to upload {filename} as it is a directory or has 0 bytes" : "امکان آپلود {filename} وجود ندارد، پوشه‌ای با این نام یا فایلی با حجم 0 بایت با این نام وجود دارد", "Total file size {size1} exceeds upload limit {size2}" : "مجموع سایز {size1} بیشتر از محدودیت آپلود {size2} است", "Not enough free space, you are uploading {size1} but only {size2} is left" : "ظرفیت لازم وجود ندارد، شما آپلودی با حجم {size1} را انجام میدهید اما تنها {size2} فضا باقی مانده است", - "Upload cancelled." : "بار گذاری لغو شد", "Could not get result from server." : "امکان دریافت نتایج از سرور وجود ندارد.", "File upload is in progress. Leaving the page now will cancel the upload." : "آپلودکردن پرونده در حال پیشرفت است. در صورت خروج از صفحه آپلود لغو میگردد. ", "Actions" : "فعالیت ها", @@ -75,11 +75,11 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n بایت"], "Favorited" : "برگزیده شده", "Favorite" : "برگزیده", - "{newname} already exists" : "{newname} هم‌اکنون وجود دارد", - "Upload" : "بارگزاری", "Text file" : "فایل متنی", "Folder" : "پوشه", "New folder" : "پوشه جدید", + "{newname} already exists" : "{newname} هم‌اکنون وجود دارد", + "Upload" : "بارگزاری", "An error occurred while trying to update the tags" : "یک خطا در حین بروزرسانی برچسب‌ها رخ داده است", "A new file or folder has been created" : "فایل یا پوشه ای ایجاد شد", "A file or folder has been changed" : "فایل یا پوشه ای به تغییر یافت", @@ -104,7 +104,6 @@ OC.L10N.register( "Maximum upload size" : "حداکثر اندازه بارگزاری", "max. possible: " : "حداکثرمقدارممکن:", "Save" : "ذخیره", - "Can not be edited from here due to insufficient permissions." : "با توجه به دسترسی محدود، امکان ویرایش از اینجا وجود ندارد.", "Settings" : "تنظیمات", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "از این آدرس استفاده کنید تا بتوانید به فایل‌های خود توسط WebDAV دسترسی پیدا کنید", diff --git a/apps/files/l10n/fa.json b/apps/files/l10n/fa.json index 0f745e7f243..ddf67b42593 100644 --- a/apps/files/l10n/fa.json +++ b/apps/files/l10n/fa.json @@ -28,10 +28,10 @@ "Favorites" : "موارد محبوب", "Home" : "خانه", "Close" : "بستن", + "Upload cancelled." : "بار گذاری لغو شد", "Unable to upload {filename} as it is a directory or has 0 bytes" : "امکان آپلود {filename} وجود ندارد، پوشه‌ای با این نام یا فایلی با حجم 0 بایت با این نام وجود دارد", "Total file size {size1} exceeds upload limit {size2}" : "مجموع سایز {size1} بیشتر از محدودیت آپلود {size2} است", "Not enough free space, you are uploading {size1} but only {size2} is left" : "ظرفیت لازم وجود ندارد، شما آپلودی با حجم {size1} را انجام میدهید اما تنها {size2} فضا باقی مانده است", - "Upload cancelled." : "بار گذاری لغو شد", "Could not get result from server." : "امکان دریافت نتایج از سرور وجود ندارد.", "File upload is in progress. Leaving the page now will cancel the upload." : "آپلودکردن پرونده در حال پیشرفت است. در صورت خروج از صفحه آپلود لغو میگردد. ", "Actions" : "فعالیت ها", @@ -73,11 +73,11 @@ "_%n byte_::_%n bytes_" : ["%n بایت"], "Favorited" : "برگزیده شده", "Favorite" : "برگزیده", - "{newname} already exists" : "{newname} هم‌اکنون وجود دارد", - "Upload" : "بارگزاری", "Text file" : "فایل متنی", "Folder" : "پوشه", "New folder" : "پوشه جدید", + "{newname} already exists" : "{newname} هم‌اکنون وجود دارد", + "Upload" : "بارگزاری", "An error occurred while trying to update the tags" : "یک خطا در حین بروزرسانی برچسب‌ها رخ داده است", "A new file or folder has been created" : "فایل یا پوشه ای ایجاد شد", "A file or folder has been changed" : "فایل یا پوشه ای به تغییر یافت", @@ -102,7 +102,6 @@ "Maximum upload size" : "حداکثر اندازه بارگزاری", "max. possible: " : "حداکثرمقدارممکن:", "Save" : "ذخیره", - "Can not be edited from here due to insufficient permissions." : "با توجه به دسترسی محدود، امکان ویرایش از اینجا وجود ندارد.", "Settings" : "تنظیمات", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "از این آدرس استفاده کنید تا بتوانید به فایل‌های خود توسط WebDAV دسترسی پیدا کنید", diff --git a/apps/files/l10n/fi_FI.js b/apps/files/l10n/fi_FI.js index cf4bb0f5792..447350e024f 100644 --- a/apps/files/l10n/fi_FI.js +++ b/apps/files/l10n/fi_FI.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Suosikit", "Home" : "Koti", "Close" : "Sulje", + "Upload cancelled." : "Lähetys peruttu.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kohdetta {filename} ei voi lähettää, koska se on joko kansio tai sen koko on 0 tavua", "Total file size {size1} exceeds upload limit {size2}" : "Yhteiskoko {size1} ylittää lähetysrajan {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ei riittävästi vapaata tilaa. Lähetyksesi koko on {size1}, mutta vain {size2} on jäljellä", - "Upload cancelled." : "Lähetys peruttu.", "Could not get result from server." : "Tuloksien saaminen palvelimelta ei onnistunut.", "File upload is in progress. Leaving the page now will cancel the upload." : "Tiedoston lähetys on meneillään. Sivulta poistuminen nyt peruu tiedoston lähetyksen.", "Actions" : "Toiminnot", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n tavu","%n tavua"], "Favorited" : "Lisätty suosikkeihin", "Favorite" : "Suosikki", - "{newname} already exists" : "{newname} on jo olemassa", - "Upload" : "Lähetä", "Text file" : "Tekstitiedosto", "New text file.txt" : "Uusi tekstitiedosto.txt", "Folder" : "Kansio", "New folder" : "Uusi kansio", + "{newname} already exists" : "{newname} on jo olemassa", + "Upload" : "Lähetä", "An error occurred while trying to update the tags" : "Tunnisteiden päivitystä yrittäessä tapahtui virhe", "A new file or folder has been created" : "Uusi tiedosto tai kansio on luotu", "A file or folder has been changed" : "Tiedostoa tai kansiota on muutettu", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Tiedostonhallinta", "Maximum upload size" : "Lähetettävän tiedoston suurin sallittu koko", "max. possible: " : "suurin mahdollinen:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM:n ollessa käytössä tämän arvon tuleminen voimaan saattaa kestää viisi minuuttia tallennushetkestä.", "Save" : "Tallenna", - "Can not be edited from here due to insufficient permissions." : "Ei muokattavissa täällä puutteellisten oikeuksien vuoksi.", "Settings" : "Asetukset", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Käytä tätä osoitetta käyttääksesi tiedostojasi WebDAVin kautta", diff --git a/apps/files/l10n/fi_FI.json b/apps/files/l10n/fi_FI.json index 56417b3c74d..aa30ccd433e 100644 --- a/apps/files/l10n/fi_FI.json +++ b/apps/files/l10n/fi_FI.json @@ -28,10 +28,10 @@ "Favorites" : "Suosikit", "Home" : "Koti", "Close" : "Sulje", + "Upload cancelled." : "Lähetys peruttu.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kohdetta {filename} ei voi lähettää, koska se on joko kansio tai sen koko on 0 tavua", "Total file size {size1} exceeds upload limit {size2}" : "Yhteiskoko {size1} ylittää lähetysrajan {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ei riittävästi vapaata tilaa. Lähetyksesi koko on {size1}, mutta vain {size2} on jäljellä", - "Upload cancelled." : "Lähetys peruttu.", "Could not get result from server." : "Tuloksien saaminen palvelimelta ei onnistunut.", "File upload is in progress. Leaving the page now will cancel the upload." : "Tiedoston lähetys on meneillään. Sivulta poistuminen nyt peruu tiedoston lähetyksen.", "Actions" : "Toiminnot", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n tavu","%n tavua"], "Favorited" : "Lisätty suosikkeihin", "Favorite" : "Suosikki", - "{newname} already exists" : "{newname} on jo olemassa", - "Upload" : "Lähetä", "Text file" : "Tekstitiedosto", "New text file.txt" : "Uusi tekstitiedosto.txt", "Folder" : "Kansio", "New folder" : "Uusi kansio", + "{newname} already exists" : "{newname} on jo olemassa", + "Upload" : "Lähetä", "An error occurred while trying to update the tags" : "Tunnisteiden päivitystä yrittäessä tapahtui virhe", "A new file or folder has been created" : "Uusi tiedosto tai kansio on luotu", "A file or folder has been changed" : "Tiedostoa tai kansiota on muutettu", @@ -103,9 +103,7 @@ "File handling" : "Tiedostonhallinta", "Maximum upload size" : "Lähetettävän tiedoston suurin sallittu koko", "max. possible: " : "suurin mahdollinen:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM:n ollessa käytössä tämän arvon tuleminen voimaan saattaa kestää viisi minuuttia tallennushetkestä.", "Save" : "Tallenna", - "Can not be edited from here due to insufficient permissions." : "Ei muokattavissa täällä puutteellisten oikeuksien vuoksi.", "Settings" : "Asetukset", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Käytä tätä osoitetta käyttääksesi tiedostojasi WebDAVin kautta", diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js index 0b290eb160a..d00f33391d4 100644 --- a/apps/files/l10n/fr.js +++ b/apps/files/l10n/fr.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoris", "Home" : "Mes fichiers", "Close" : "Fermer", + "Upload cancelled." : "Envoi annulé.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossible d'envoyer {filename} car il s'agit d'un répertoire ou d'un fichier de taille nulle", "Total file size {size1} exceeds upload limit {size2}" : "La taille totale du fichier {size1} excède la taille maximale d'envoi {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Espace libre insuffisant : vous tentez d'envoyer {size1} mais seulement {size2} sont disponibles", - "Upload cancelled." : "Envoi annulé.", "Could not get result from server." : "Ne peut recevoir les résultats du serveur.", "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", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marqué comme favori", "Favorite" : "Favoris", - "{newname} already exists" : "{newname} existe déjà", - "Upload" : "Chargement", "Text file" : "Fichier texte", "New text file.txt" : "Nouveau fichier texte.txt", "Folder" : "Dossier", "New folder" : "Nouveau dossier", + "{newname} already exists" : "{newname} existe déjà", + "Upload" : "Chargement", "An error occurred while trying to update the tags" : "Une erreur est survenue lors de la mise à jour des étiquettes", "A new file or folder has been created" : "Un nouveau fichier ou répertoire a été créé", "A file or folder has been changed" : "Un fichier ou un répertoire a été modifié", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Gestion de fichiers", "Maximum upload size" : "Taille max. d'envoi", "max. possible: " : "Max. possible :", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Avec PHP-FPM, il peut se passer jusqu'à 5 minutes avant que cette valeur ne soit appliquée.", "Save" : "Sauvegarder", - "Can not be edited from here due to insufficient permissions." : "Ne peut être modifié ici à cause de permissions insuffisantes.", "Settings" : "Paramètres", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilisez cette adresse pour accéder à vos fichiers par WebDAV", diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json index 5f51bdee302..9d30823e265 100644 --- a/apps/files/l10n/fr.json +++ b/apps/files/l10n/fr.json @@ -28,10 +28,10 @@ "Favorites" : "Favoris", "Home" : "Mes fichiers", "Close" : "Fermer", + "Upload cancelled." : "Envoi annulé.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossible d'envoyer {filename} car il s'agit d'un répertoire ou d'un fichier de taille nulle", "Total file size {size1} exceeds upload limit {size2}" : "La taille totale du fichier {size1} excède la taille maximale d'envoi {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Espace libre insuffisant : vous tentez d'envoyer {size1} mais seulement {size2} sont disponibles", - "Upload cancelled." : "Envoi annulé.", "Could not get result from server." : "Ne peut recevoir les résultats du serveur.", "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", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marqué comme favori", "Favorite" : "Favoris", - "{newname} already exists" : "{newname} existe déjà", - "Upload" : "Chargement", "Text file" : "Fichier texte", "New text file.txt" : "Nouveau fichier texte.txt", "Folder" : "Dossier", "New folder" : "Nouveau dossier", + "{newname} already exists" : "{newname} existe déjà", + "Upload" : "Chargement", "An error occurred while trying to update the tags" : "Une erreur est survenue lors de la mise à jour des étiquettes", "A new file or folder has been created" : "Un nouveau fichier ou répertoire a été créé", "A file or folder has been changed" : "Un fichier ou un répertoire a été modifié", @@ -103,9 +103,7 @@ "File handling" : "Gestion de fichiers", "Maximum upload size" : "Taille max. d'envoi", "max. possible: " : "Max. possible :", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Avec PHP-FPM, il peut se passer jusqu'à 5 minutes avant que cette valeur ne soit appliquée.", "Save" : "Sauvegarder", - "Can not be edited from here due to insufficient permissions." : "Ne peut être modifié ici à cause de permissions insuffisantes.", "Settings" : "Paramètres", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilisez cette adresse pour accéder à vos fichiers par WebDAV", diff --git a/apps/files/l10n/gl.js b/apps/files/l10n/gl.js index 2910ab97ea4..2713148bbb9 100644 --- a/apps/files/l10n/gl.js +++ b/apps/files/l10n/gl.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Inicio", "Close" : "Pechar", + "Upload cancelled." : "Envío cancelado.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Non é posíbel enviar {filename}, xa que ou é un directorio ou ten 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "O tamaño total do ficheiro {size1} excede do límite de envío {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Non hai espazo libre abondo, o seu envío é de {size1} mais só dispón de {size2}", - "Upload cancelled." : "Envío cancelado.", "Could not get result from server." : "Non foi posíbel obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "O envío do ficheiro está en proceso. Saír agora da páxina cancelará o envío.", "Actions" : "Accións", @@ -75,10 +75,10 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Marcado como favorito", "Favorite" : "Favorito", - "Upload" : "Enviar", "Text file" : "Ficheiro de texto", "Folder" : "Cartafol", "New folder" : "Novo cartafol", + "Upload" : "Enviar", "An error occurred while trying to update the tags" : "Produciuse un erro ao tentar actualizar as etiquetas", "A new file or folder has been created" : "Creouse un novo ficheiro ou cartafol", "A file or folder has been changed" : "Cambiouse un ficheiro ou cartafol", @@ -101,7 +101,6 @@ OC.L10N.register( "Maximum upload size" : "Tamaño máximo do envío", "max. possible: " : "máx. posíbel: ", "Save" : "Gardar", - "Can not be edited from here due to insufficient permissions." : "Non pode ser editado desde aquí por mor de falta de permisos.", "Settings" : "Axustes", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Empregue esta ligazón para acceder aos seus ficheiros mediante WebDAV", diff --git a/apps/files/l10n/gl.json b/apps/files/l10n/gl.json index 386df1569a9..f04420d11a7 100644 --- a/apps/files/l10n/gl.json +++ b/apps/files/l10n/gl.json @@ -28,10 +28,10 @@ "Favorites" : "Favoritos", "Home" : "Inicio", "Close" : "Pechar", + "Upload cancelled." : "Envío cancelado.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Non é posíbel enviar {filename}, xa que ou é un directorio ou ten 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "O tamaño total do ficheiro {size1} excede do límite de envío {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Non hai espazo libre abondo, o seu envío é de {size1} mais só dispón de {size2}", - "Upload cancelled." : "Envío cancelado.", "Could not get result from server." : "Non foi posíbel obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "O envío do ficheiro está en proceso. Saír agora da páxina cancelará o envío.", "Actions" : "Accións", @@ -73,10 +73,10 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Marcado como favorito", "Favorite" : "Favorito", - "Upload" : "Enviar", "Text file" : "Ficheiro de texto", "Folder" : "Cartafol", "New folder" : "Novo cartafol", + "Upload" : "Enviar", "An error occurred while trying to update the tags" : "Produciuse un erro ao tentar actualizar as etiquetas", "A new file or folder has been created" : "Creouse un novo ficheiro ou cartafol", "A file or folder has been changed" : "Cambiouse un ficheiro ou cartafol", @@ -99,7 +99,6 @@ "Maximum upload size" : "Tamaño máximo do envío", "max. possible: " : "máx. posíbel: ", "Save" : "Gardar", - "Can not be edited from here due to insufficient permissions." : "Non pode ser editado desde aquí por mor de falta de permisos.", "Settings" : "Axustes", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Empregue esta ligazón para acceder aos seus ficheiros mediante WebDAV", diff --git a/apps/files/l10n/he.js b/apps/files/l10n/he.js index 1eaf54aad71..36fba4bd7f0 100644 --- a/apps/files/l10n/he.js +++ b/apps/files/l10n/he.js @@ -38,10 +38,10 @@ OC.L10N.register( "File name cannot be empty." : "שם קובץ אינו יכול להיות ריק", "Your storage is almost full ({usedSpacePercent}%)" : "שטח האחסון שלך כמעט מלא ({usedSpacePercent}%)", "Favorite" : "מועדף", - "Upload" : "העלאה", "Text file" : "קובץ טקסט", "Folder" : "תיקייה", "New folder" : "תיקייה חדשה", + "Upload" : "העלאה", "A new file or folder has been created" : "קובץ או תיקייה חדשים נוצרו", "A file or folder has been changed" : "קובץ או תיקייה שונו", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", diff --git a/apps/files/l10n/he.json b/apps/files/l10n/he.json index fe56eef25c2..61fe8ca29b7 100644 --- a/apps/files/l10n/he.json +++ b/apps/files/l10n/he.json @@ -36,10 +36,10 @@ "File name cannot be empty." : "שם קובץ אינו יכול להיות ריק", "Your storage is almost full ({usedSpacePercent}%)" : "שטח האחסון שלך כמעט מלא ({usedSpacePercent}%)", "Favorite" : "מועדף", - "Upload" : "העלאה", "Text file" : "קובץ טקסט", "Folder" : "תיקייה", "New folder" : "תיקייה חדשה", + "Upload" : "העלאה", "A new file or folder has been created" : "קובץ או תיקייה חדשים נוצרו", "A file or folder has been changed" : "קובץ או תיקייה שונו", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", diff --git a/apps/files/l10n/hi.js b/apps/files/l10n/hi.js index 2a546af9b1e..3b6da840e0d 100644 --- a/apps/files/l10n/hi.js +++ b/apps/files/l10n/hi.js @@ -5,8 +5,8 @@ OC.L10N.register( "Close" : "बंद करें ", "Details" : "विवरण ", "Error" : "त्रुटि", - "Upload" : "अपलोड ", "New folder" : "नया फ़ोल्डर", + "Upload" : "अपलोड ", "Save" : "सहेजें", "Settings" : "सेटिंग्स" }, diff --git a/apps/files/l10n/hi.json b/apps/files/l10n/hi.json index 47830eca416..a5a2ba34b01 100644 --- a/apps/files/l10n/hi.json +++ b/apps/files/l10n/hi.json @@ -3,8 +3,8 @@ "Close" : "बंद करें ", "Details" : "विवरण ", "Error" : "त्रुटि", - "Upload" : "अपलोड ", "New folder" : "नया फ़ोल्डर", + "Upload" : "अपलोड ", "Save" : "सहेजें", "Settings" : "सेटिंग्स" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/apps/files/l10n/hr.js b/apps/files/l10n/hr.js index d6e48d1da13..a15e52dcd49 100644 --- a/apps/files/l10n/hr.js +++ b/apps/files/l10n/hr.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoriti", "Home" : "Kuća", "Close" : "Zatvorite", + "Upload cancelled." : "Učitavanje je prekinuto.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nije moguće učitati {filename} jer je ili direktorij ili ima 0 bajta", "Total file size {size1} exceeds upload limit {size2}" : "Ukupna veličina datoteke {size1} premašuje ograničenje unosa {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nedovoljno slobodnog prostora, vi učitavate {size1} a samo je {size2} preostalo", - "Upload cancelled." : "Učitavanje je prekinuto.", "Could not get result from server." : "Nemoguće dobiti rezultat od poslužitelja.", "File upload is in progress. Leaving the page now will cancel the upload." : "Učitavanje datoteke je u tijeku. Napuštanje stranice prekinut će učitavanje.", "Actions" : "Radnje", @@ -68,10 +68,10 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Vaš prostor za pohranu je skoro pun ({usedSpacePercent}%)", "Favorited" : "Favoritovan", "Favorite" : "Favorit", - "Upload" : "Učitavanje", "Text file" : "Tekstualna datoteka", "Folder" : "Mapa", "New folder" : "Nova mapa", + "Upload" : "Učitavanje", "A new file or folder has been created" : "Nova datoteka ili nova mapa su kreirani", "A file or folder has been changed" : "Datoteka ili mapa su promijenjeni", "A file or folder has been deleted" : "Datoteka ili mapa su izbrisani", diff --git a/apps/files/l10n/hr.json b/apps/files/l10n/hr.json index 99f7737b66c..e0463579f4a 100644 --- a/apps/files/l10n/hr.json +++ b/apps/files/l10n/hr.json @@ -28,10 +28,10 @@ "Favorites" : "Favoriti", "Home" : "Kuća", "Close" : "Zatvorite", + "Upload cancelled." : "Učitavanje je prekinuto.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nije moguće učitati {filename} jer je ili direktorij ili ima 0 bajta", "Total file size {size1} exceeds upload limit {size2}" : "Ukupna veličina datoteke {size1} premašuje ograničenje unosa {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nedovoljno slobodnog prostora, vi učitavate {size1} a samo je {size2} preostalo", - "Upload cancelled." : "Učitavanje je prekinuto.", "Could not get result from server." : "Nemoguće dobiti rezultat od poslužitelja.", "File upload is in progress. Leaving the page now will cancel the upload." : "Učitavanje datoteke je u tijeku. Napuštanje stranice prekinut će učitavanje.", "Actions" : "Radnje", @@ -66,10 +66,10 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Vaš prostor za pohranu je skoro pun ({usedSpacePercent}%)", "Favorited" : "Favoritovan", "Favorite" : "Favorit", - "Upload" : "Učitavanje", "Text file" : "Tekstualna datoteka", "Folder" : "Mapa", "New folder" : "Nova mapa", + "Upload" : "Učitavanje", "A new file or folder has been created" : "Nova datoteka ili nova mapa su kreirani", "A file or folder has been changed" : "Datoteka ili mapa su promijenjeni", "A file or folder has been deleted" : "Datoteka ili mapa su izbrisani", diff --git a/apps/files/l10n/hu_HU.js b/apps/files/l10n/hu_HU.js index 5eff7a8f842..48e9bfb168b 100644 --- a/apps/files/l10n/hu_HU.js +++ b/apps/files/l10n/hu_HU.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Kedvencek", "Home" : "Otthoni", "Close" : "Bezárás", + "Upload cancelled." : "A feltöltést megszakítottuk.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "A(z) {filename} állomány nem tölthető fel, mert ez vagy egy mappa, vagy pedig 0 bájtból áll.", "Total file size {size1} exceeds upload limit {size2}" : "A teljes fájlméret: {size1} meghaladja a feltöltési limitet: {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nincs elég szabad hely. A feltöltés mérete {size1}, de csak ennyi hely van: {size2}.", - "Upload cancelled." : "A feltöltést megszakítottuk.", "Could not get result from server." : "A kiszolgálótól nem kapható meg a művelet eredménye.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fájlfeltöltés van folyamatban. Az oldal elhagyása megszakítja a feltöltést.", "Actions" : "Műveletek", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n bájt","%n bájt"], "Favorited" : "Kedvenc", "Favorite" : "Kedvenc", - "{newname} already exists" : "{newname} már létezik", - "Upload" : "Feltöltés", "Text file" : "Szövegfájl", "New text file.txt" : "Új szöveges fájl.txt", "Folder" : "Mappa", "New folder" : "Új mappa", + "{newname} already exists" : "{newname} már létezik", + "Upload" : "Feltöltés", "An error occurred while trying to update the tags" : "Hiba történt, miközben megpróbálta frissíteni a címkéket", "A new file or folder has been created" : "Új fájl vagy könyvtár létrehozása", "A file or folder has been changed" : "Fájl vagy könyvtár módosítása", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Fájlkezelés", "Maximum upload size" : "Maximális feltölthető fájlméret", "max. possible: " : "max. lehetséges: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM-mel ez az érték életbe lépése mentés után akár 5 percbe is telhet.", "Save" : "Mentés", - "Can not be edited from here due to insufficient permissions." : "Innen nem lehet szerkeszteni az elégtelen jogosultság miatt ", "Settings" : "Beállítások", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Ezt a címet használja, ha WebDAV-on keresztül szeretné elérni a fájljait", diff --git a/apps/files/l10n/hu_HU.json b/apps/files/l10n/hu_HU.json index da5eed09733..c72dfa0d48b 100644 --- a/apps/files/l10n/hu_HU.json +++ b/apps/files/l10n/hu_HU.json @@ -28,10 +28,10 @@ "Favorites" : "Kedvencek", "Home" : "Otthoni", "Close" : "Bezárás", + "Upload cancelled." : "A feltöltést megszakítottuk.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "A(z) {filename} állomány nem tölthető fel, mert ez vagy egy mappa, vagy pedig 0 bájtból áll.", "Total file size {size1} exceeds upload limit {size2}" : "A teljes fájlméret: {size1} meghaladja a feltöltési limitet: {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nincs elég szabad hely. A feltöltés mérete {size1}, de csak ennyi hely van: {size2}.", - "Upload cancelled." : "A feltöltést megszakítottuk.", "Could not get result from server." : "A kiszolgálótól nem kapható meg a művelet eredménye.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fájlfeltöltés van folyamatban. Az oldal elhagyása megszakítja a feltöltést.", "Actions" : "Műveletek", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n bájt","%n bájt"], "Favorited" : "Kedvenc", "Favorite" : "Kedvenc", - "{newname} already exists" : "{newname} már létezik", - "Upload" : "Feltöltés", "Text file" : "Szövegfájl", "New text file.txt" : "Új szöveges fájl.txt", "Folder" : "Mappa", "New folder" : "Új mappa", + "{newname} already exists" : "{newname} már létezik", + "Upload" : "Feltöltés", "An error occurred while trying to update the tags" : "Hiba történt, miközben megpróbálta frissíteni a címkéket", "A new file or folder has been created" : "Új fájl vagy könyvtár létrehozása", "A file or folder has been changed" : "Fájl vagy könyvtár módosítása", @@ -103,9 +103,7 @@ "File handling" : "Fájlkezelés", "Maximum upload size" : "Maximális feltölthető fájlméret", "max. possible: " : "max. lehetséges: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM-mel ez az érték életbe lépése mentés után akár 5 percbe is telhet.", "Save" : "Mentés", - "Can not be edited from here due to insufficient permissions." : "Innen nem lehet szerkeszteni az elégtelen jogosultság miatt ", "Settings" : "Beállítások", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Ezt a címet használja, ha WebDAV-on keresztül szeretné elérni a fájljait", diff --git a/apps/files/l10n/ia.js b/apps/files/l10n/ia.js index 84f3b4d8c45..f1db4466ea1 100644 --- a/apps/files/l10n/ia.js +++ b/apps/files/l10n/ia.js @@ -16,10 +16,10 @@ OC.L10N.register( "Modified" : "Modificate", "New" : "Nove", "File name cannot be empty." : "Le nomine de file non pote esser vacue.", - "Upload" : "Incargar", "Text file" : "File de texto", "Folder" : "Dossier", "New folder" : "Nove dossier", + "Upload" : "Incargar", "A new file or folder has been created" : "Un nove file o dossier ha essite create", "A file or folder has been changed" : "Un nove file o dossier ha essite modificate", "A file or folder has been deleted" : "Un nove file o dossier ha essite delite", diff --git a/apps/files/l10n/ia.json b/apps/files/l10n/ia.json index 2843f8789ac..e7990404b98 100644 --- a/apps/files/l10n/ia.json +++ b/apps/files/l10n/ia.json @@ -14,10 +14,10 @@ "Modified" : "Modificate", "New" : "Nove", "File name cannot be empty." : "Le nomine de file non pote esser vacue.", - "Upload" : "Incargar", "Text file" : "File de texto", "Folder" : "Dossier", "New folder" : "Nove dossier", + "Upload" : "Incargar", "A new file or folder has been created" : "Un nove file o dossier ha essite create", "A file or folder has been changed" : "Un nove file o dossier ha essite modificate", "A file or folder has been deleted" : "Un nove file o dossier ha essite delite", diff --git a/apps/files/l10n/id.js b/apps/files/l10n/id.js index f02a6d79c4d..f1ad4fd1f69 100644 --- a/apps/files/l10n/id.js +++ b/apps/files/l10n/id.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favorit", "Home" : "Rumah", "Close" : "Tutup", + "Upload cancelled." : "Pengunggahan dibatalkan.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Tidak dapat mengunggah {filename} karena ini sebuah direktori atau memiliki ukuran 0 byte", "Total file size {size1} exceeds upload limit {size2}" : "Jumlah ukuran berkas {size1} melampaui batas unggah {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ruang bebas tidak mencukupi, Anda mengunggah {size1} tetapi hanya {size2} yang tersisa", - "Upload cancelled." : "Pengunggahan dibatalkan.", "Could not get result from server." : "Tidak mendapatkan hasil dari server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Berkas sedang diunggah. Meninggalkan halaman ini akan membatalkan proses.", "Actions" : "Tindakan", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte"], "Favorited" : "Difavoritkan", "Favorite" : "Favorit", - "{newname} already exists" : "{newname} sudah ada", - "Upload" : "Unggah", "Text file" : "Berkas teks", "New text file.txt" : "Teks baru file.txt", "Folder" : "Folder", "New folder" : "Map baru", + "{newname} already exists" : "{newname} sudah ada", + "Upload" : "Unggah", "An error occurred while trying to update the tags" : "Terjadi kesalahan saat mencoba untuk memperbarui label", "A new file or folder has been created" : "Sebuah berkas atau folder baru telah dibuat", "A file or folder has been changed" : "Sebuah berkas atau folder telah diubah", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Penanganan berkas", "Maximum upload size" : "Ukuran pengunggahan maksimum", "max. possible: " : "Kemungkinan maks.:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Dengan PHP-FPM, nilai ini bisa memerlukan waktu hingga 5 menit untuk berlaku setelah penyimpanan.", "Save" : "Simpan", - "Can not be edited from here due to insufficient permissions." : "Tidak dapat disunting dari sini karena tidak memiliki izin.", "Settings" : "Pengaturan", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Gunakan alamat ini untuk mengakses Berkas via WebDAV", diff --git a/apps/files/l10n/id.json b/apps/files/l10n/id.json index 773f6b8f5a7..0d357165370 100644 --- a/apps/files/l10n/id.json +++ b/apps/files/l10n/id.json @@ -28,10 +28,10 @@ "Favorites" : "Favorit", "Home" : "Rumah", "Close" : "Tutup", + "Upload cancelled." : "Pengunggahan dibatalkan.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Tidak dapat mengunggah {filename} karena ini sebuah direktori atau memiliki ukuran 0 byte", "Total file size {size1} exceeds upload limit {size2}" : "Jumlah ukuran berkas {size1} melampaui batas unggah {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ruang bebas tidak mencukupi, Anda mengunggah {size1} tetapi hanya {size2} yang tersisa", - "Upload cancelled." : "Pengunggahan dibatalkan.", "Could not get result from server." : "Tidak mendapatkan hasil dari server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Berkas sedang diunggah. Meninggalkan halaman ini akan membatalkan proses.", "Actions" : "Tindakan", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte"], "Favorited" : "Difavoritkan", "Favorite" : "Favorit", - "{newname} already exists" : "{newname} sudah ada", - "Upload" : "Unggah", "Text file" : "Berkas teks", "New text file.txt" : "Teks baru file.txt", "Folder" : "Folder", "New folder" : "Map baru", + "{newname} already exists" : "{newname} sudah ada", + "Upload" : "Unggah", "An error occurred while trying to update the tags" : "Terjadi kesalahan saat mencoba untuk memperbarui label", "A new file or folder has been created" : "Sebuah berkas atau folder baru telah dibuat", "A file or folder has been changed" : "Sebuah berkas atau folder telah diubah", @@ -103,9 +103,7 @@ "File handling" : "Penanganan berkas", "Maximum upload size" : "Ukuran pengunggahan maksimum", "max. possible: " : "Kemungkinan maks.:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Dengan PHP-FPM, nilai ini bisa memerlukan waktu hingga 5 menit untuk berlaku setelah penyimpanan.", "Save" : "Simpan", - "Can not be edited from here due to insufficient permissions." : "Tidak dapat disunting dari sini karena tidak memiliki izin.", "Settings" : "Pengaturan", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Gunakan alamat ini untuk mengakses Berkas via WebDAV", diff --git a/apps/files/l10n/is.js b/apps/files/l10n/is.js index 780dbe4301f..f56579fa9c0 100644 --- a/apps/files/l10n/is.js +++ b/apps/files/l10n/is.js @@ -28,9 +28,9 @@ OC.L10N.register( "Modified" : "Breytt", "New" : "Nýtt", "File name cannot be empty." : "Nafn skráar má ekki vera tómt", - "Upload" : "Senda inn", "Text file" : "Texta skrá", "Folder" : "Mappa", + "Upload" : "Senda inn", "File handling" : "Meðhöndlun skrár", "Maximum upload size" : "Hámarks stærð innsendingar", "max. possible: " : "hámark mögulegt: ", diff --git a/apps/files/l10n/is.json b/apps/files/l10n/is.json index aed9568f7d0..8a6da48f408 100644 --- a/apps/files/l10n/is.json +++ b/apps/files/l10n/is.json @@ -26,9 +26,9 @@ "Modified" : "Breytt", "New" : "Nýtt", "File name cannot be empty." : "Nafn skráar má ekki vera tómt", - "Upload" : "Senda inn", "Text file" : "Texta skrá", "Folder" : "Mappa", + "Upload" : "Senda inn", "File handling" : "Meðhöndlun skrár", "Maximum upload size" : "Hámarks stærð innsendingar", "max. possible: " : "hámark mögulegt: ", diff --git a/apps/files/l10n/it.js b/apps/files/l10n/it.js index c8286c66a57..7fdd7170887 100644 --- a/apps/files/l10n/it.js +++ b/apps/files/l10n/it.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Preferiti", "Home" : "Home", "Close" : "Chiudi", + "Upload cancelled." : "Caricamento annullato.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossibile caricare {filename} poiché è una cartella oppure ha una dimensione di 0 byte.", "Total file size {size1} exceeds upload limit {size2}" : "La dimensione totale del file {size1} supera il limite di caricamento {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Spazio insufficiente, stai caricando {size1}, ma è rimasto solo {size2}", - "Upload cancelled." : "Caricamento annullato.", "Could not get result from server." : "Impossibile ottenere il risultato dal server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Caricamento del file in corso. La chiusura della pagina annullerà il caricamento.", "Actions" : "Azioni", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n byte"], "Favorited" : "Preferiti", "Favorite" : "Preferito", - "{newname} already exists" : "{newname} esiste già", - "Upload" : "Carica", "Text file" : "File di testo", "New text file.txt" : "Nuovo file di testo.txt", "Folder" : "Cartella", "New folder" : "Nuova cartella", + "{newname} already exists" : "{newname} esiste già", + "Upload" : "Carica", "An error occurred while trying to update the tags" : "Si è verificato un errore durante il tentativo di aggiornare le etichette", "A new file or folder has been created" : "Un nuovo file o cartella è stato creato", "A file or folder has been changed" : "Un file o una cartella è stato modificato", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Gestione file", "Maximum upload size" : "Dimensione massima caricamento", "max. possible: " : "numero mass.: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Con PHP-FPM questo valore potrebbe richiedere fino a 5 minuti perché abbia effetto dopo il salvataggio.", "Save" : "Salva", - "Can not be edited from here due to insufficient permissions." : "Non può essere modificato da qui a causa della mancanza di permessi.", "Settings" : "Impostazioni", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilizza questo indirizzo per accedere ai tuoi file con WebDAV", diff --git a/apps/files/l10n/it.json b/apps/files/l10n/it.json index 6f6092c5c15..9e5bee70191 100644 --- a/apps/files/l10n/it.json +++ b/apps/files/l10n/it.json @@ -28,10 +28,10 @@ "Favorites" : "Preferiti", "Home" : "Home", "Close" : "Chiudi", + "Upload cancelled." : "Caricamento annullato.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossibile caricare {filename} poiché è una cartella oppure ha una dimensione di 0 byte.", "Total file size {size1} exceeds upload limit {size2}" : "La dimensione totale del file {size1} supera il limite di caricamento {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Spazio insufficiente, stai caricando {size1}, ma è rimasto solo {size2}", - "Upload cancelled." : "Caricamento annullato.", "Could not get result from server." : "Impossibile ottenere il risultato dal server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Caricamento del file in corso. La chiusura della pagina annullerà il caricamento.", "Actions" : "Azioni", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n byte"], "Favorited" : "Preferiti", "Favorite" : "Preferito", - "{newname} already exists" : "{newname} esiste già", - "Upload" : "Carica", "Text file" : "File di testo", "New text file.txt" : "Nuovo file di testo.txt", "Folder" : "Cartella", "New folder" : "Nuova cartella", + "{newname} already exists" : "{newname} esiste già", + "Upload" : "Carica", "An error occurred while trying to update the tags" : "Si è verificato un errore durante il tentativo di aggiornare le etichette", "A new file or folder has been created" : "Un nuovo file o cartella è stato creato", "A file or folder has been changed" : "Un file o una cartella è stato modificato", @@ -103,9 +103,7 @@ "File handling" : "Gestione file", "Maximum upload size" : "Dimensione massima caricamento", "max. possible: " : "numero mass.: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Con PHP-FPM questo valore potrebbe richiedere fino a 5 minuti perché abbia effetto dopo il salvataggio.", "Save" : "Salva", - "Can not be edited from here due to insufficient permissions." : "Non può essere modificato da qui a causa della mancanza di permessi.", "Settings" : "Impostazioni", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilizza questo indirizzo per accedere ai tuoi file con WebDAV", diff --git a/apps/files/l10n/ja.js b/apps/files/l10n/ja.js index 052562d13ee..53eb8dca351 100644 --- a/apps/files/l10n/ja.js +++ b/apps/files/l10n/ja.js @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n バイト"], "Favorited" : "お気に入り済", "Favorite" : "お気に入り", - "{newname} already exists" : "{newname} はすでに存在します", - "Upload" : "アップロード", "Text file" : "テキストファイル", "New text file.txt" : "新規のテキストファイル作成", "Folder" : "フォルダー", "New folder" : "新しいフォルダー", + "{newname} already exists" : "{newname} はすでに存在します", + "Upload" : "アップロード", "An error occurred while trying to update the tags" : "タグを更新する際にエラーが発生しました", "A new file or folder has been created" : "新しいファイルまたはフォルダーを作成したとき", "A file or folder has been changed" : "ファイルまたはフォルダーを変更したとき", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "ファイル操作", "Maximum upload size" : "最大アップロードサイズ", "max. possible: " : "最大容量: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM の場合は値を変更後、反映されるのに5分程度かかります。", "Save" : "保存", - "Can not be edited from here due to insufficient permissions." : "権限不足のため直接編集することはできません。", "Settings" : "設定", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "WebDAV経由でのファイルアクセスにはこのアドレスを利用してください", diff --git a/apps/files/l10n/ja.json b/apps/files/l10n/ja.json index 4534e787e0f..36983beafc2 100644 --- a/apps/files/l10n/ja.json +++ b/apps/files/l10n/ja.json @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n バイト"], "Favorited" : "お気に入り済", "Favorite" : "お気に入り", - "{newname} already exists" : "{newname} はすでに存在します", - "Upload" : "アップロード", "Text file" : "テキストファイル", "New text file.txt" : "新規のテキストファイル作成", "Folder" : "フォルダー", "New folder" : "新しいフォルダー", + "{newname} already exists" : "{newname} はすでに存在します", + "Upload" : "アップロード", "An error occurred while trying to update the tags" : "タグを更新する際にエラーが発生しました", "A new file or folder has been created" : "新しいファイルまたはフォルダーを作成したとき", "A file or folder has been changed" : "ファイルまたはフォルダーを変更したとき", @@ -103,9 +103,7 @@ "File handling" : "ファイル操作", "Maximum upload size" : "最大アップロードサイズ", "max. possible: " : "最大容量: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM の場合は値を変更後、反映されるのに5分程度かかります。", "Save" : "保存", - "Can not be edited from here due to insufficient permissions." : "権限不足のため直接編集することはできません。", "Settings" : "設定", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "WebDAV経由でのファイルアクセスにはこのアドレスを利用してください", diff --git a/apps/files/l10n/ka_GE.js b/apps/files/l10n/ka_GE.js index c76e75864f9..fe22f22ceb3 100644 --- a/apps/files/l10n/ka_GE.js +++ b/apps/files/l10n/ka_GE.js @@ -36,10 +36,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!", "Your storage is almost full ({usedSpacePercent}%)" : "თქვენი საცავი თითქმის გადაივსო ({usedSpacePercent}%)", "Favorite" : "ფავორიტი", - "Upload" : "ატვირთვა", "Text file" : "ტექსტური ფაილი", "Folder" : "საქაღალდე", "New folder" : "ახალი ფოლდერი", + "Upload" : "ატვირთვა", "File handling" : "ფაილის დამუშავება", "Maximum upload size" : "მაქსიმუმ ატვირთის ზომა", "max. possible: " : "მაქს. შესაძლებელი:", diff --git a/apps/files/l10n/ka_GE.json b/apps/files/l10n/ka_GE.json index 058bee2618b..8f23f671b7e 100644 --- a/apps/files/l10n/ka_GE.json +++ b/apps/files/l10n/ka_GE.json @@ -34,10 +34,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!", "Your storage is almost full ({usedSpacePercent}%)" : "თქვენი საცავი თითქმის გადაივსო ({usedSpacePercent}%)", "Favorite" : "ფავორიტი", - "Upload" : "ატვირთვა", "Text file" : "ტექსტური ფაილი", "Folder" : "საქაღალდე", "New folder" : "ახალი ფოლდერი", + "Upload" : "ატვირთვა", "File handling" : "ფაილის დამუშავება", "Maximum upload size" : "მაქსიმუმ ატვირთის ზომა", "max. possible: " : "მაქს. შესაძლებელი:", diff --git a/apps/files/l10n/km.js b/apps/files/l10n/km.js index 030bdd35eda..b63a3a90ef0 100644 --- a/apps/files/l10n/km.js +++ b/apps/files/l10n/km.js @@ -21,10 +21,10 @@ OC.L10N.register( "Modified" : "បាន​កែ​ប្រែ", "New" : "ថ្មី", "File name cannot be empty." : "ឈ្មោះ​ឯកសារ​មិន​អាច​នៅ​ទទេ​បាន​ឡើយ។", - "Upload" : "ផ្ទុក​ឡើង", "Text file" : "ឯកសារ​អក្សរ", "Folder" : "ថត", "New folder" : "ថត​ថ្មី", + "Upload" : "ផ្ទុក​ឡើង", "You created %1$s" : "អ្នក​បាន​បង្កើត %1$s", "%2$s created %1$s" : "%2$s បាន​បង្កើត %1$s", "You changed %1$s" : "អ្នក​បាន​ផ្លាស់​ប្ដូរ %1$s", diff --git a/apps/files/l10n/km.json b/apps/files/l10n/km.json index 679787a5ce2..8dda2ab2cb1 100644 --- a/apps/files/l10n/km.json +++ b/apps/files/l10n/km.json @@ -19,10 +19,10 @@ "Modified" : "បាន​កែ​ប្រែ", "New" : "ថ្មី", "File name cannot be empty." : "ឈ្មោះ​ឯកសារ​មិន​អាច​នៅ​ទទេ​បាន​ឡើយ។", - "Upload" : "ផ្ទុក​ឡើង", "Text file" : "ឯកសារ​អក្សរ", "Folder" : "ថត", "New folder" : "ថត​ថ្មី", + "Upload" : "ផ្ទុក​ឡើង", "You created %1$s" : "អ្នក​បាន​បង្កើត %1$s", "%2$s created %1$s" : "%2$s បាន​បង្កើត %1$s", "You changed %1$s" : "អ្នក​បាន​ផ្លាស់​ប្ដូរ %1$s", diff --git a/apps/files/l10n/kn.js b/apps/files/l10n/kn.js index 7538d9b033e..b1c793b1ef3 100644 --- a/apps/files/l10n/kn.js +++ b/apps/files/l10n/kn.js @@ -53,10 +53,10 @@ OC.L10N.register( "File name cannot be empty." : "ಕಡತ ಹೆಸರು ಖಾಲಿ ಇರುವಂತಿಲ್ಲ.", "Favorited" : "ಅಚ್ಚುಮೆಚ್ಚಿನವು", "Favorite" : "ಅಚ್ಚುಮೆಚ್ಚಿನ", - "Upload" : "ವರ್ಗಾಯಿಸಿ", "Text file" : "ಸರಳಾಕ್ಷರದ ಕಡತ", "Folder" : "ಕಡತಕೋಶ", "New folder" : "ಹೊಸ ಕಡತಕೋಶ", + "Upload" : "ವರ್ಗಾಯಿಸಿ", "Upload (max. %s)" : "ವರ್ಗಾವಣೆ (ಗರಿಷ್ಠ %s)", "File handling" : "ಕಡತ ನಿರ್ವಹಣೆ", "Maximum upload size" : "ಗರಿಷ್ಠ ವರ್ಗಾವಣೆ ಗಾತ್ರ", diff --git a/apps/files/l10n/kn.json b/apps/files/l10n/kn.json index b9f55d4151a..6667f3ae01f 100644 --- a/apps/files/l10n/kn.json +++ b/apps/files/l10n/kn.json @@ -51,10 +51,10 @@ "File name cannot be empty." : "ಕಡತ ಹೆಸರು ಖಾಲಿ ಇರುವಂತಿಲ್ಲ.", "Favorited" : "ಅಚ್ಚುಮೆಚ್ಚಿನವು", "Favorite" : "ಅಚ್ಚುಮೆಚ್ಚಿನ", - "Upload" : "ವರ್ಗಾಯಿಸಿ", "Text file" : "ಸರಳಾಕ್ಷರದ ಕಡತ", "Folder" : "ಕಡತಕೋಶ", "New folder" : "ಹೊಸ ಕಡತಕೋಶ", + "Upload" : "ವರ್ಗಾಯಿಸಿ", "Upload (max. %s)" : "ವರ್ಗಾವಣೆ (ಗರಿಷ್ಠ %s)", "File handling" : "ಕಡತ ನಿರ್ವಹಣೆ", "Maximum upload size" : "ಗರಿಷ್ಠ ವರ್ಗಾವಣೆ ಗಾತ್ರ", diff --git a/apps/files/l10n/ko.js b/apps/files/l10n/ko.js index 67b5e869e5e..70ee488454a 100644 --- a/apps/files/l10n/ko.js +++ b/apps/files/l10n/ko.js @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n바이트"], "Favorited" : "책갈피에 추가됨", "Favorite" : "즐겨찾기", - "{newname} already exists" : "{newname} 항목이 이미 존재함", - "Upload" : "업로드", "Text file" : "텍스트 파일", "New text file.txt" : "새 텍스트 파일.txt", "Folder" : "폴더", "New folder" : "새 폴더", + "{newname} already exists" : "{newname} 항목이 이미 존재함", + "Upload" : "업로드", "An error occurred while trying to update the tags" : "태그를 업데이트하는 중 오류 발생", "A new file or folder has been created" : "새 파일이나 폴더가 생성됨", "A file or folder has been changed" : "파일이나 폴더가 변경됨", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "파일 처리", "Maximum upload size" : "최대 업로드 크기", "max. possible: " : "최대 가능:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM을 사용하고 있으면 설정 변화가 적용될 때까지 5분 정도 걸릴 수 있습니다.", "Save" : "저장", - "Can not be edited from here due to insufficient permissions." : "권한이 부족하므로 여기에서 편집할 수 없습니다.", "Settings" : "설정", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "WebDAV로 파일에 접근하려면 이 주소를 사용하십시오", diff --git a/apps/files/l10n/ko.json b/apps/files/l10n/ko.json index 3c88e502b1f..65e61d8ec49 100644 --- a/apps/files/l10n/ko.json +++ b/apps/files/l10n/ko.json @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n바이트"], "Favorited" : "책갈피에 추가됨", "Favorite" : "즐겨찾기", - "{newname} already exists" : "{newname} 항목이 이미 존재함", - "Upload" : "업로드", "Text file" : "텍스트 파일", "New text file.txt" : "새 텍스트 파일.txt", "Folder" : "폴더", "New folder" : "새 폴더", + "{newname} already exists" : "{newname} 항목이 이미 존재함", + "Upload" : "업로드", "An error occurred while trying to update the tags" : "태그를 업데이트하는 중 오류 발생", "A new file or folder has been created" : "새 파일이나 폴더가 생성됨", "A file or folder has been changed" : "파일이나 폴더가 변경됨", @@ -103,9 +103,7 @@ "File handling" : "파일 처리", "Maximum upload size" : "최대 업로드 크기", "max. possible: " : "최대 가능:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM을 사용하고 있으면 설정 변화가 적용될 때까지 5분 정도 걸릴 수 있습니다.", "Save" : "저장", - "Can not be edited from here due to insufficient permissions." : "권한이 부족하므로 여기에서 편집할 수 없습니다.", "Settings" : "설정", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "WebDAV로 파일에 접근하려면 이 주소를 사용하십시오", diff --git a/apps/files/l10n/ku_IQ.js b/apps/files/l10n/ku_IQ.js index 32af16b3673..7a995636ec9 100644 --- a/apps/files/l10n/ku_IQ.js +++ b/apps/files/l10n/ku_IQ.js @@ -8,8 +8,8 @@ OC.L10N.register( "Select" : "دیاریکردنی", "Error" : "هه‌ڵه", "Name" : "ناو", - "Upload" : "بارکردن", "Folder" : "بوخچه", + "Upload" : "بارکردن", "Save" : "پاشکه‌وتکردن", "Settings" : "ڕێکخستنه‌کان" }, diff --git a/apps/files/l10n/ku_IQ.json b/apps/files/l10n/ku_IQ.json index 4f1068bbb04..f39269efd39 100644 --- a/apps/files/l10n/ku_IQ.json +++ b/apps/files/l10n/ku_IQ.json @@ -6,8 +6,8 @@ "Select" : "دیاریکردنی", "Error" : "هه‌ڵه", "Name" : "ناو", - "Upload" : "بارکردن", "Folder" : "بوخچه", + "Upload" : "بارکردن", "Save" : "پاشکه‌وتکردن", "Settings" : "ڕێکخستنه‌کان" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/apps/files/l10n/lb.js b/apps/files/l10n/lb.js index 047aac2dbb3..97cb28477f1 100644 --- a/apps/files/l10n/lb.js +++ b/apps/files/l10n/lb.js @@ -24,10 +24,10 @@ OC.L10N.register( "Size" : "Gréisst", "Modified" : "Geännert", "New" : "Nei", - "Upload" : "Eroplueden", "Text file" : "Text Fichier", "Folder" : "Dossier", "New folder" : "Neien Dossier", + "Upload" : "Eroplueden", "File handling" : "Fichier handling", "Maximum upload size" : "Maximum Upload Gréisst ", "max. possible: " : "max. méiglech:", diff --git a/apps/files/l10n/lb.json b/apps/files/l10n/lb.json index f298444a35f..c3dae7b0b88 100644 --- a/apps/files/l10n/lb.json +++ b/apps/files/l10n/lb.json @@ -22,10 +22,10 @@ "Size" : "Gréisst", "Modified" : "Geännert", "New" : "Nei", - "Upload" : "Eroplueden", "Text file" : "Text Fichier", "Folder" : "Dossier", "New folder" : "Neien Dossier", + "Upload" : "Eroplueden", "File handling" : "Fichier handling", "Maximum upload size" : "Maximum Upload Gréisst ", "max. possible: " : "max. méiglech:", diff --git a/apps/files/l10n/lt_LT.js b/apps/files/l10n/lt_LT.js index f2ea62593c1..ac7084cfc2d 100644 --- a/apps/files/l10n/lt_LT.js +++ b/apps/files/l10n/lt_LT.js @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Failų tvarkymas", "Maximum upload size" : "Maksimalus įkeliamo failo dydis", "max. possible: " : "maks. galima:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Su PHP-FPM reikšmės atnaujinimas gali užtrukti iki 5 minučių po pakeitimo.", "Save" : "Išsaugoti", - "Can not be edited from here due to insufficient permissions." : "Negali būti redaguojamas iš čia dėl leidimų trūkumo.", "Settings" : "Nustatymai", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Naudokite šį adresą, kad pasiektumėte savo failus per WebDAV", diff --git a/apps/files/l10n/lt_LT.json b/apps/files/l10n/lt_LT.json index 56455896282..aef54469542 100644 --- a/apps/files/l10n/lt_LT.json +++ b/apps/files/l10n/lt_LT.json @@ -103,9 +103,7 @@ "File handling" : "Failų tvarkymas", "Maximum upload size" : "Maksimalus įkeliamo failo dydis", "max. possible: " : "maks. galima:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Su PHP-FPM reikšmės atnaujinimas gali užtrukti iki 5 minučių po pakeitimo.", "Save" : "Išsaugoti", - "Can not be edited from here due to insufficient permissions." : "Negali būti redaguojamas iš čia dėl leidimų trūkumo.", "Settings" : "Nustatymai", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Naudokite šį adresą, kad pasiektumėte savo failus per WebDAV", diff --git a/apps/files/l10n/lv.js b/apps/files/l10n/lv.js index f0d5b4212b0..ad18fe93244 100644 --- a/apps/files/l10n/lv.js +++ b/apps/files/l10n/lv.js @@ -69,10 +69,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["atrasts pēc '{filter}'","atrasts pēc '{filter}'","atrasti pēc '{filter}'"], "Favorited" : "Favorīti", "Favorite" : "Iecienītais", - "Upload" : "Augšupielādēt", "Text file" : "Teksta datne", "Folder" : "Mape", "New folder" : "Jauna mape", + "Upload" : "Augšupielādēt", "An error occurred while trying to update the tags" : "Atjaunojot atzīmes notika kļūda", "A new file or folder has been created" : "Izveidots jauns fails vai mape", "A file or folder has been changed" : "Izmainīts fails vai mape", diff --git a/apps/files/l10n/lv.json b/apps/files/l10n/lv.json index 14d0b4093df..16ac9adf08d 100644 --- a/apps/files/l10n/lv.json +++ b/apps/files/l10n/lv.json @@ -67,10 +67,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["atrasts pēc '{filter}'","atrasts pēc '{filter}'","atrasti pēc '{filter}'"], "Favorited" : "Favorīti", "Favorite" : "Iecienītais", - "Upload" : "Augšupielādēt", "Text file" : "Teksta datne", "Folder" : "Mape", "New folder" : "Jauna mape", + "Upload" : "Augšupielādēt", "An error occurred while trying to update the tags" : "Atjaunojot atzīmes notika kļūda", "A new file or folder has been created" : "Izveidots jauns fails vai mape", "A file or folder has been changed" : "Izmainīts fails vai mape", diff --git a/apps/files/l10n/mk.js b/apps/files/l10n/mk.js index e6265c851e8..a87cdcdc371 100644 --- a/apps/files/l10n/mk.js +++ b/apps/files/l10n/mk.js @@ -47,10 +47,10 @@ OC.L10N.register( "File name cannot be empty." : "Името на датотеката не може да биде празно.", "Your storage is full, files can not be updated or synced anymore!" : "Вашиот сториџ е полн, датотеките веќе не можат да се освежуваат или синхронизираат!", "Your storage is almost full ({usedSpacePercent}%)" : "Вашиот сториџ е скоро полн ({usedSpacePercent}%)", - "Upload" : "Подигни", "Text file" : "Текстуална датотека", "Folder" : "Папка", "New folder" : "Нова папка", + "Upload" : "Подигни", "You created %1$s" : "Вие креиравте %1$s", "%2$s created %1$s" : "%2$s креирано %1$s", "You changed %1$s" : "Вие изменивте %1$s", diff --git a/apps/files/l10n/mk.json b/apps/files/l10n/mk.json index 0806f7d0966..49e2fce36d7 100644 --- a/apps/files/l10n/mk.json +++ b/apps/files/l10n/mk.json @@ -45,10 +45,10 @@ "File name cannot be empty." : "Името на датотеката не може да биде празно.", "Your storage is full, files can not be updated or synced anymore!" : "Вашиот сториџ е полн, датотеките веќе не можат да се освежуваат или синхронизираат!", "Your storage is almost full ({usedSpacePercent}%)" : "Вашиот сториџ е скоро полн ({usedSpacePercent}%)", - "Upload" : "Подигни", "Text file" : "Текстуална датотека", "Folder" : "Папка", "New folder" : "Нова папка", + "Upload" : "Подигни", "You created %1$s" : "Вие креиравте %1$s", "%2$s created %1$s" : "%2$s креирано %1$s", "You changed %1$s" : "Вие изменивте %1$s", diff --git a/apps/files/l10n/ms_MY.js b/apps/files/l10n/ms_MY.js index 7ef2afeb84e..b57c1e61ca9 100644 --- a/apps/files/l10n/ms_MY.js +++ b/apps/files/l10n/ms_MY.js @@ -21,9 +21,9 @@ OC.L10N.register( "Size" : "Saiz", "Modified" : "Dimodifikasi", "New" : "Baru", - "Upload" : "Muat naik", "Text file" : "Fail teks", "Folder" : "Folder", + "Upload" : "Muat naik", "You created %1$s" : "Anda telah membina %1$s", "%2$s created %1$s" : "%2$s membina %1$s", "You changed %1$s" : "Anda menukar %1$s", diff --git a/apps/files/l10n/ms_MY.json b/apps/files/l10n/ms_MY.json index aec2dd50949..e9db1fcad9d 100644 --- a/apps/files/l10n/ms_MY.json +++ b/apps/files/l10n/ms_MY.json @@ -19,9 +19,9 @@ "Size" : "Saiz", "Modified" : "Dimodifikasi", "New" : "Baru", - "Upload" : "Muat naik", "Text file" : "Fail teks", "Folder" : "Folder", + "Upload" : "Muat naik", "You created %1$s" : "Anda telah membina %1$s", "%2$s created %1$s" : "%2$s membina %1$s", "You changed %1$s" : "Anda menukar %1$s", diff --git a/apps/files/l10n/nb_NO.js b/apps/files/l10n/nb_NO.js index 7fe475a6a22..a1f8def347e 100644 --- a/apps/files/l10n/nb_NO.js +++ b/apps/files/l10n/nb_NO.js @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Er favoritt", "Favorite" : "Gjør til favoritt", - "{newname} already exists" : "{newname} finnes allerede", - "Upload" : "Last opp", "Text file" : "Tekstfil", "New text file.txt" : "Ny tekstfil.txt", "Folder" : "Mappe", "New folder" : "Ny mappe", + "{newname} already exists" : "{newname} finnes allerede", + "Upload" : "Last opp", "An error occurred while trying to update the tags" : "En feil oppstod under oppdatering av taggene", "A new file or folder has been created" : "En ny fil eller mappe ble opprettet", "A file or folder has been changed" : "En fil eller mappe ble endret", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Filhåndtering", "Maximum upload size" : "Største opplastingsstørrelse", "max. possible: " : "max. mulige:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Med PHP-FPM kan det ta inntil 5 minutter fra denne verdien lagres til den trer i kraft.", "Save" : "Lagre", - "Can not be edited from here due to insufficient permissions." : "Kan ikke redigeres her pga. manglende rettigheter.", "Settings" : "Innstillinger", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Bruk denne adressen for å få tilgang til filene dine via WebDAV", diff --git a/apps/files/l10n/nb_NO.json b/apps/files/l10n/nb_NO.json index 69e8ca742aa..6d7ee493008 100644 --- a/apps/files/l10n/nb_NO.json +++ b/apps/files/l10n/nb_NO.json @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Er favoritt", "Favorite" : "Gjør til favoritt", - "{newname} already exists" : "{newname} finnes allerede", - "Upload" : "Last opp", "Text file" : "Tekstfil", "New text file.txt" : "Ny tekstfil.txt", "Folder" : "Mappe", "New folder" : "Ny mappe", + "{newname} already exists" : "{newname} finnes allerede", + "Upload" : "Last opp", "An error occurred while trying to update the tags" : "En feil oppstod under oppdatering av taggene", "A new file or folder has been created" : "En ny fil eller mappe ble opprettet", "A file or folder has been changed" : "En fil eller mappe ble endret", @@ -103,9 +103,7 @@ "File handling" : "Filhåndtering", "Maximum upload size" : "Største opplastingsstørrelse", "max. possible: " : "max. mulige:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Med PHP-FPM kan det ta inntil 5 minutter fra denne verdien lagres til den trer i kraft.", "Save" : "Lagre", - "Can not be edited from here due to insufficient permissions." : "Kan ikke redigeres her pga. manglende rettigheter.", "Settings" : "Innstillinger", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Bruk denne adressen for å få tilgang til filene dine via WebDAV", diff --git a/apps/files/l10n/nl.js b/apps/files/l10n/nl.js index 53ec6c1d804..d60598ca147 100644 --- a/apps/files/l10n/nl.js +++ b/apps/files/l10n/nl.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favorieten", "Home" : "Thuis", "Close" : "Sluiten", + "Upload cancelled." : "Uploaden geannuleerd.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan {filename} niet uploaden omdat het een map is of 0 bytes groot is", "Total file size {size1} exceeds upload limit {size2}" : "Totale bestandsgrootte {size1} groter dan uploadlimiet {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Niet genoeg vrije ruimte. U upload {size1}, maar is is slechts {size2} beschikbaar", - "Upload cancelled." : "Uploaden geannuleerd.", "Could not get result from server." : "Kon het resultaat van de server niet terugkrijgen.", "File upload is in progress. Leaving the page now will cancel the upload." : "Bestandsupload is bezig. Wanneer de pagina nu verlaten wordt, stopt de upload.", "Actions" : "Acties", @@ -74,12 +74,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Favoriet", "Favorite" : "Favoriet", - "{newname} already exists" : "{newname} bestaat al", - "Upload" : "Uploaden", "Text file" : "Tekstbestand", "New text file.txt" : "Nieuw tekstbestand.txt", "Folder" : "Map", "New folder" : "Nieuwe map", + "{newname} already exists" : "{newname} bestaat al", + "Upload" : "Uploaden", "An error occurred while trying to update the tags" : "Er trad een fout op bij uw poging de tags bij te werken", "A new file or folder has been created" : "Een nieuw bestand of map is aangemaakt", "A file or folder has been changed" : "Een bestand of map is gewijzigd", @@ -104,9 +104,7 @@ OC.L10N.register( "File handling" : "Bestand", "Maximum upload size" : "Maximale bestandsgrootte voor uploads", "max. possible: " : "max. mogelijk: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Met PHP-FPM kan het tot 5 minuten duren voordat de aanpassing van deze waarde effect heeft.", "Save" : "Bewaren", - "Can not be edited from here due to insufficient permissions." : "Kan hier niet worden bewerkt wegens onvoldoende permissies.", "Settings" : "Instellingen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Gebruik deze link om uw bestanden via WebDAV te benaderen", diff --git a/apps/files/l10n/nl.json b/apps/files/l10n/nl.json index 6a077b1cc1a..28f80c09af7 100644 --- a/apps/files/l10n/nl.json +++ b/apps/files/l10n/nl.json @@ -28,10 +28,10 @@ "Favorites" : "Favorieten", "Home" : "Thuis", "Close" : "Sluiten", + "Upload cancelled." : "Uploaden geannuleerd.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan {filename} niet uploaden omdat het een map is of 0 bytes groot is", "Total file size {size1} exceeds upload limit {size2}" : "Totale bestandsgrootte {size1} groter dan uploadlimiet {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Niet genoeg vrije ruimte. U upload {size1}, maar is is slechts {size2} beschikbaar", - "Upload cancelled." : "Uploaden geannuleerd.", "Could not get result from server." : "Kon het resultaat van de server niet terugkrijgen.", "File upload is in progress. Leaving the page now will cancel the upload." : "Bestandsupload is bezig. Wanneer de pagina nu verlaten wordt, stopt de upload.", "Actions" : "Acties", @@ -72,12 +72,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Favoriet", "Favorite" : "Favoriet", - "{newname} already exists" : "{newname} bestaat al", - "Upload" : "Uploaden", "Text file" : "Tekstbestand", "New text file.txt" : "Nieuw tekstbestand.txt", "Folder" : "Map", "New folder" : "Nieuwe map", + "{newname} already exists" : "{newname} bestaat al", + "Upload" : "Uploaden", "An error occurred while trying to update the tags" : "Er trad een fout op bij uw poging de tags bij te werken", "A new file or folder has been created" : "Een nieuw bestand of map is aangemaakt", "A file or folder has been changed" : "Een bestand of map is gewijzigd", @@ -102,9 +102,7 @@ "File handling" : "Bestand", "Maximum upload size" : "Maximale bestandsgrootte voor uploads", "max. possible: " : "max. mogelijk: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Met PHP-FPM kan het tot 5 minuten duren voordat de aanpassing van deze waarde effect heeft.", "Save" : "Bewaren", - "Can not be edited from here due to insufficient permissions." : "Kan hier niet worden bewerkt wegens onvoldoende permissies.", "Settings" : "Instellingen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Gebruik deze link om uw bestanden via WebDAV te benaderen", diff --git a/apps/files/l10n/nn_NO.js b/apps/files/l10n/nn_NO.js index 924670d596b..6d9e9f4acdd 100644 --- a/apps/files/l10n/nn_NO.js +++ b/apps/files/l10n/nn_NO.js @@ -22,8 +22,8 @@ OC.L10N.register( "Favorites" : "Favorittar", "Home" : "Heime", "Close" : "Lukk", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "Klarte ikkje å lasta opp {filename} sidan det er ei mappe eller er 0 byte.", "Upload cancelled." : "Opplasting avbroten.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "Klarte ikkje å lasta opp {filename} sidan det er ei mappe eller er 0 byte.", "Could not get result from server." : "Klarte ikkje å henta resultat frå tenaren.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fila lastar no opp. Viss du forlèt sida no vil opplastinga verta avbroten.", "Actions" : "Handlingar", @@ -47,10 +47,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "Lagringa di er full, kan ikkje lenger oppdatera eller synkronisera!", "Your storage is almost full ({usedSpacePercent}%)" : "Lagringa di er nesten full ({usedSpacePercent} %)", "Favorite" : "Favoritt", - "Upload" : "Last opp", "Text file" : "Tekst fil", "Folder" : "Mappe", "New folder" : "Ny mappe", + "Upload" : "Last opp", "A new file or folder has been created" : "Ei ny fil eller mappe er oppretta", "A file or folder has been changed" : "Ei fil eller mappe er endra", "A file or folder has been deleted" : "Ei fil eller mappe er sletta", diff --git a/apps/files/l10n/nn_NO.json b/apps/files/l10n/nn_NO.json index 05e6f0a9d2d..277c50de6da 100644 --- a/apps/files/l10n/nn_NO.json +++ b/apps/files/l10n/nn_NO.json @@ -20,8 +20,8 @@ "Favorites" : "Favorittar", "Home" : "Heime", "Close" : "Lukk", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "Klarte ikkje å lasta opp {filename} sidan det er ei mappe eller er 0 byte.", "Upload cancelled." : "Opplasting avbroten.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "Klarte ikkje å lasta opp {filename} sidan det er ei mappe eller er 0 byte.", "Could not get result from server." : "Klarte ikkje å henta resultat frå tenaren.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fila lastar no opp. Viss du forlèt sida no vil opplastinga verta avbroten.", "Actions" : "Handlingar", @@ -45,10 +45,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "Lagringa di er full, kan ikkje lenger oppdatera eller synkronisera!", "Your storage is almost full ({usedSpacePercent}%)" : "Lagringa di er nesten full ({usedSpacePercent} %)", "Favorite" : "Favoritt", - "Upload" : "Last opp", "Text file" : "Tekst fil", "Folder" : "Mappe", "New folder" : "Ny mappe", + "Upload" : "Last opp", "A new file or folder has been created" : "Ei ny fil eller mappe er oppretta", "A file or folder has been changed" : "Ei fil eller mappe er endra", "A file or folder has been deleted" : "Ei fil eller mappe er sletta", diff --git a/apps/files/l10n/oc.js b/apps/files/l10n/oc.js index 6a0a05c782a..d702fcace3d 100644 --- a/apps/files/l10n/oc.js +++ b/apps/files/l10n/oc.js @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marcat coma favorit", "Favorite" : "Favorit", - "{newname} already exists" : "{new_name} existís ja", - "Upload" : "Cargament", "Text file" : "Fichièr tèxte", "New text file.txt" : "Novèl fichièr tèxte .txt", "Folder" : "Dorsièr", "New folder" : "Novèl dorsièr", + "{newname} already exists" : "{new_name} existís ja", + "Upload" : "Cargament", "An error occurred while trying to update the tags" : "Una error s'es produsida al moment de la mesa a jorn de las etiquetas", "A new file or folder has been created" : "Un novèl fichièr o repertòri es estat creat", "A file or folder has been changed" : "Un fichièr o un repertòri es estat modificat", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Gestion de fichièrs", "Maximum upload size" : "Talha max. de mandadís", "max. possible: " : "Max. possible :", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Amb PHP-FPM, se pòdon passar fins a 5 minutas abans qu'aquesta valor siá aplicada.", "Save" : "Salvar", - "Can not be edited from here due to insufficient permissions." : "Pòt pas èsser modificat aicí a causa de permissions insufisentas.", "Settings" : "Paramètres", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilizatz aquesta adreça per accedir a vòstres fichièrs per WebDAV", diff --git a/apps/files/l10n/oc.json b/apps/files/l10n/oc.json index 0577b75076a..ec91aa3ccba 100644 --- a/apps/files/l10n/oc.json +++ b/apps/files/l10n/oc.json @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marcat coma favorit", "Favorite" : "Favorit", - "{newname} already exists" : "{new_name} existís ja", - "Upload" : "Cargament", "Text file" : "Fichièr tèxte", "New text file.txt" : "Novèl fichièr tèxte .txt", "Folder" : "Dorsièr", "New folder" : "Novèl dorsièr", + "{newname} already exists" : "{new_name} existís ja", + "Upload" : "Cargament", "An error occurred while trying to update the tags" : "Una error s'es produsida al moment de la mesa a jorn de las etiquetas", "A new file or folder has been created" : "Un novèl fichièr o repertòri es estat creat", "A file or folder has been changed" : "Un fichièr o un repertòri es estat modificat", @@ -103,9 +103,7 @@ "File handling" : "Gestion de fichièrs", "Maximum upload size" : "Talha max. de mandadís", "max. possible: " : "Max. possible :", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Amb PHP-FPM, se pòdon passar fins a 5 minutas abans qu'aquesta valor siá aplicada.", "Save" : "Salvar", - "Can not be edited from here due to insufficient permissions." : "Pòt pas èsser modificat aicí a causa de permissions insufisentas.", "Settings" : "Paramètres", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilizatz aquesta adreça per accedir a vòstres fichièrs per WebDAV", diff --git a/apps/files/l10n/pl.js b/apps/files/l10n/pl.js index 5cba43675dd..e7a208bc639 100644 --- a/apps/files/l10n/pl.js +++ b/apps/files/l10n/pl.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Ulubione", "Home" : "Dom", "Close" : "Zamknij", + "Upload cancelled." : "Wczytywanie anulowane.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nie można przesłać {filename} być może jest katalogiem lub posiada 0 bajtów", "Total file size {size1} exceeds upload limit {size2}" : "Całkowity rozmiar {size1} przekracza limit uploadu {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Brak wolnej przestrzeni, przesyłasz {size1} a pozostało tylko {size2}", - "Upload cancelled." : "Wczytywanie anulowane.", "Could not get result from server." : "Nie można uzyskać wyniku z serwera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Wysyłanie pliku jest w toku. Jeśli opuścisz tę stronę, wysyłanie zostanie przerwane.", "Actions" : "Akcje", @@ -70,10 +70,10 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Twój magazyn jest prawie pełny ({usedSpacePercent}%)", "Favorited" : "Ulubione", "Favorite" : "Ulubione", - "Upload" : "Wyślij", "Text file" : "Plik tekstowy", "Folder" : "Folder", "New folder" : "Nowy folder", + "Upload" : "Wyślij", "A new file or folder has been created" : "Nowy plik lub folder został utworzony", "A file or folder has been changed" : "Plik lub folder został zmieniony", "A file or folder has been deleted" : "Plik lub folder został usunięty", diff --git a/apps/files/l10n/pl.json b/apps/files/l10n/pl.json index 5b09f326134..4af3ab766e4 100644 --- a/apps/files/l10n/pl.json +++ b/apps/files/l10n/pl.json @@ -28,10 +28,10 @@ "Favorites" : "Ulubione", "Home" : "Dom", "Close" : "Zamknij", + "Upload cancelled." : "Wczytywanie anulowane.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nie można przesłać {filename} być może jest katalogiem lub posiada 0 bajtów", "Total file size {size1} exceeds upload limit {size2}" : "Całkowity rozmiar {size1} przekracza limit uploadu {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Brak wolnej przestrzeni, przesyłasz {size1} a pozostało tylko {size2}", - "Upload cancelled." : "Wczytywanie anulowane.", "Could not get result from server." : "Nie można uzyskać wyniku z serwera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Wysyłanie pliku jest w toku. Jeśli opuścisz tę stronę, wysyłanie zostanie przerwane.", "Actions" : "Akcje", @@ -68,10 +68,10 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Twój magazyn jest prawie pełny ({usedSpacePercent}%)", "Favorited" : "Ulubione", "Favorite" : "Ulubione", - "Upload" : "Wyślij", "Text file" : "Plik tekstowy", "Folder" : "Folder", "New folder" : "Nowy folder", + "Upload" : "Wyślij", "A new file or folder has been created" : "Nowy plik lub folder został utworzony", "A file or folder has been changed" : "Plik lub folder został zmieniony", "A file or folder has been deleted" : "Plik lub folder został usunięty", diff --git a/apps/files/l10n/pt_BR.js b/apps/files/l10n/pt_BR.js index 70d38e747ba..158ef08608d 100644 --- a/apps/files/l10n/pt_BR.js +++ b/apps/files/l10n/pt_BR.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Home", "Close" : "Fechar", + "Upload cancelled." : "Envio cancelado.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Incapaz de fazer o envio de {filename}, pois é um diretório ou tem 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "O tamanho total do arquivo {size1} excede o limite de envio {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Não há espaço suficiente, você está enviando {size1} mas resta apenas {size2}", - "Upload cancelled." : "Envio cancelado.", "Could not get result from server." : "Não foi possível obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "Envio de arquivo em andamento. Sair da página agora resultará no cancelamento do envio.", "Actions" : "Ações", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Favorito", "Favorite" : "Favorito", - "{newname} already exists" : "{newname} já existe", - "Upload" : "Enviar", "Text file" : "Arquivo texto", "New text file.txt" : "Novo texto file.txt", "Folder" : "Pasta", "New folder" : "Nova pasta", + "{newname} already exists" : "{newname} já existe", + "Upload" : "Enviar", "An error occurred while trying to update the tags" : "Ocorreu um erro enquanto tentava atualizar as etiquetas", "A new file or folder has been created" : "Um novo arquivo ou pasta foi criado", "A file or folder has been changed" : "Um arquivo ou pasta foi modificado", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Tratamento de Arquivo", "Maximum upload size" : "Tamanho máximo para envio", "max. possible: " : "max. possível:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Com PHP-FPM este valor pode demorar até 5 minutos para fazer efeito depois de ser salvo.", "Save" : "Salvar", - "Can not be edited from here due to insufficient permissions." : "Não pode ser editado a partir daqui devido a permissões insuficientes.", "Settings" : "Configurações", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use este endereço para ter acesso aos seus Arquivos via WebDAV", diff --git a/apps/files/l10n/pt_BR.json b/apps/files/l10n/pt_BR.json index d0023e7d5be..af539480d95 100644 --- a/apps/files/l10n/pt_BR.json +++ b/apps/files/l10n/pt_BR.json @@ -28,10 +28,10 @@ "Favorites" : "Favoritos", "Home" : "Home", "Close" : "Fechar", + "Upload cancelled." : "Envio cancelado.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Incapaz de fazer o envio de {filename}, pois é um diretório ou tem 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "O tamanho total do arquivo {size1} excede o limite de envio {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Não há espaço suficiente, você está enviando {size1} mas resta apenas {size2}", - "Upload cancelled." : "Envio cancelado.", "Could not get result from server." : "Não foi possível obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "Envio de arquivo em andamento. Sair da página agora resultará no cancelamento do envio.", "Actions" : "Ações", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Favorito", "Favorite" : "Favorito", - "{newname} already exists" : "{newname} já existe", - "Upload" : "Enviar", "Text file" : "Arquivo texto", "New text file.txt" : "Novo texto file.txt", "Folder" : "Pasta", "New folder" : "Nova pasta", + "{newname} already exists" : "{newname} já existe", + "Upload" : "Enviar", "An error occurred while trying to update the tags" : "Ocorreu um erro enquanto tentava atualizar as etiquetas", "A new file or folder has been created" : "Um novo arquivo ou pasta foi criado", "A file or folder has been changed" : "Um arquivo ou pasta foi modificado", @@ -103,9 +103,7 @@ "File handling" : "Tratamento de Arquivo", "Maximum upload size" : "Tamanho máximo para envio", "max. possible: " : "max. possível:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Com PHP-FPM este valor pode demorar até 5 minutos para fazer efeito depois de ser salvo.", "Save" : "Salvar", - "Can not be edited from here due to insufficient permissions." : "Não pode ser editado a partir daqui devido a permissões insuficientes.", "Settings" : "Configurações", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use este endereço para ter acesso aos seus Arquivos via WebDAV", diff --git a/apps/files/l10n/pt_PT.js b/apps/files/l10n/pt_PT.js index 5474826994f..537abb936b1 100644 --- a/apps/files/l10n/pt_PT.js +++ b/apps/files/l10n/pt_PT.js @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Manuseamento do ficheiro", "Maximum upload size" : "Tamanho máximo de envio", "max. possible: " : "Máx. possível: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Com PHP-FPM este valor poderá demorar até 5 minutos para ser aplicado depois de guardar.", "Save" : "Guardar", - "Can not be edited from here due to insufficient permissions." : "Não pode ser editado a partir daqui devido a permissões insuficientes.", "Settings" : "Definições", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilize esta ligação para aceder aos seus ficheiros via WebDAV", diff --git a/apps/files/l10n/pt_PT.json b/apps/files/l10n/pt_PT.json index 44bf606a97f..20e8dd808cc 100644 --- a/apps/files/l10n/pt_PT.json +++ b/apps/files/l10n/pt_PT.json @@ -103,9 +103,7 @@ "File handling" : "Manuseamento do ficheiro", "Maximum upload size" : "Tamanho máximo de envio", "max. possible: " : "Máx. possível: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Com PHP-FPM este valor poderá demorar até 5 minutos para ser aplicado depois de guardar.", "Save" : "Guardar", - "Can not be edited from here due to insufficient permissions." : "Não pode ser editado a partir daqui devido a permissões insuficientes.", "Settings" : "Definições", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilize esta ligação para aceder aos seus ficheiros via WebDAV", diff --git a/apps/files/l10n/ro.js b/apps/files/l10n/ro.js index 83593b4ba8a..c3dca30abed 100644 --- a/apps/files/l10n/ro.js +++ b/apps/files/l10n/ro.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favorite", "Home" : "Acasă", "Close" : "Închide", + "Upload cancelled." : "Încărcare anulată.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți", "Total file size {size1} exceeds upload limit {size2}" : "Mărimea fișierului este {size1} ce depășește limita de încărcare de {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas", - "Upload cancelled." : "Încărcare anulată.", "Could not get result from server." : "Nu se poate obține rezultatul de la server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", "Actions" : "Acțiuni", @@ -65,10 +65,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!", "Your storage is almost full ({usedSpacePercent}%)" : "Spațiul de stocare este aproape plin ({usedSpacePercent}%)", "Favorite" : "Favorit", - "Upload" : "Încărcă", "Text file" : "Fișier text", "Folder" : "Dosar", "New folder" : "Un nou dosar", + "Upload" : "Încărcă", "A new file or folder has been created" : "Un nou fișier sau dosar a fost creat", "A file or folder has been changed" : "Un nou fișier sau dosar a fost modificat", "A file or folder has been deleted" : "Un nou fișier sau dosar a fost șters", diff --git a/apps/files/l10n/ro.json b/apps/files/l10n/ro.json index a2544bba28d..0d2f4497ff4 100644 --- a/apps/files/l10n/ro.json +++ b/apps/files/l10n/ro.json @@ -28,10 +28,10 @@ "Favorites" : "Favorite", "Home" : "Acasă", "Close" : "Închide", + "Upload cancelled." : "Încărcare anulată.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți", "Total file size {size1} exceeds upload limit {size2}" : "Mărimea fișierului este {size1} ce depășește limita de încărcare de {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas", - "Upload cancelled." : "Încărcare anulată.", "Could not get result from server." : "Nu se poate obține rezultatul de la server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", "Actions" : "Acțiuni", @@ -63,10 +63,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!", "Your storage is almost full ({usedSpacePercent}%)" : "Spațiul de stocare este aproape plin ({usedSpacePercent}%)", "Favorite" : "Favorit", - "Upload" : "Încărcă", "Text file" : "Fișier text", "Folder" : "Dosar", "New folder" : "Un nou dosar", + "Upload" : "Încărcă", "A new file or folder has been created" : "Un nou fișier sau dosar a fost creat", "A file or folder has been changed" : "Un nou fișier sau dosar a fost modificat", "A file or folder has been deleted" : "Un nou fișier sau dosar a fost șters", diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js index 270cc3c6a85..254e701a17c 100644 --- a/apps/files/l10n/ru.js +++ b/apps/files/l10n/ru.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Избранное", "Home" : "Главная", "Close" : "Закрыть", + "Upload cancelled." : "Загрузка отменена.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Невозможно загрузить {filename}, так как это либо каталог, либо файл нулевого размера", "Total file size {size1} exceeds upload limit {size2}" : "Полный размер файла {size1} превышает лимит по загрузке {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Недостаточно свободного места, Вы загружаете {size1}, но осталось только {size2}", - "Upload cancelled." : "Загрузка отменена.", "Could not get result from server." : "Не удалось получить ответ от сервера.", "File upload is in progress. Leaving the page now will cancel the upload." : "Идёт загрузка файла. Покинув страницу, вы прервёте загрузку.", "Actions" : "Действия", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n байт","%n байта","%n байтов","%n байта(ов)"], "Favorited" : "Избранное", "Favorite" : "Избранное", - "{newname} already exists" : "{newname} уже существует", - "Upload" : "Загрузить", "Text file" : "Текстовый файл", "New text file.txt" : "Новый текстовый документ.txt", "Folder" : "Каталог", "New folder" : "Новый каталог", + "{newname} already exists" : "{newname} уже существует", + "Upload" : "Загрузить", "An error occurred while trying to update the tags" : "Во время обновления тегов возникла ошибка", "A new file or folder has been created" : "Создан новый файл или каталог", "A file or folder has been changed" : "Изменён файл или каталог", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Управление файлами", "Maximum upload size" : "Максимальный размер загружаемого файла", "max. possible: " : "макс. возможно: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "При использовании PHP-FPM может потребоваться до 5 минут, чтобы это значение встпуило в силу после сохранения.", "Save" : "Сохранить", - "Can not be edited from here due to insufficient permissions." : "Невозможно отредактировать здесь из-за нехватки полномочий.", "Settings" : "Настройки", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Используйте этот адрес для доступа файлам через WebDAV", diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json index 36aae3834a9..7666ebb75d4 100644 --- a/apps/files/l10n/ru.json +++ b/apps/files/l10n/ru.json @@ -28,10 +28,10 @@ "Favorites" : "Избранное", "Home" : "Главная", "Close" : "Закрыть", + "Upload cancelled." : "Загрузка отменена.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Невозможно загрузить {filename}, так как это либо каталог, либо файл нулевого размера", "Total file size {size1} exceeds upload limit {size2}" : "Полный размер файла {size1} превышает лимит по загрузке {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Недостаточно свободного места, Вы загружаете {size1}, но осталось только {size2}", - "Upload cancelled." : "Загрузка отменена.", "Could not get result from server." : "Не удалось получить ответ от сервера.", "File upload is in progress. Leaving the page now will cancel the upload." : "Идёт загрузка файла. Покинув страницу, вы прервёте загрузку.", "Actions" : "Действия", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n байт","%n байта","%n байтов","%n байта(ов)"], "Favorited" : "Избранное", "Favorite" : "Избранное", - "{newname} already exists" : "{newname} уже существует", - "Upload" : "Загрузить", "Text file" : "Текстовый файл", "New text file.txt" : "Новый текстовый документ.txt", "Folder" : "Каталог", "New folder" : "Новый каталог", + "{newname} already exists" : "{newname} уже существует", + "Upload" : "Загрузить", "An error occurred while trying to update the tags" : "Во время обновления тегов возникла ошибка", "A new file or folder has been created" : "Создан новый файл или каталог", "A file or folder has been changed" : "Изменён файл или каталог", @@ -103,9 +103,7 @@ "File handling" : "Управление файлами", "Maximum upload size" : "Максимальный размер загружаемого файла", "max. possible: " : "макс. возможно: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "При использовании PHP-FPM может потребоваться до 5 минут, чтобы это значение встпуило в силу после сохранения.", "Save" : "Сохранить", - "Can not be edited from here due to insufficient permissions." : "Невозможно отредактировать здесь из-за нехватки полномочий.", "Settings" : "Настройки", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Используйте этот адрес для доступа файлам через WebDAV", diff --git a/apps/files/l10n/si_LK.js b/apps/files/l10n/si_LK.js index 60cd10813d9..9b2696d4530 100644 --- a/apps/files/l10n/si_LK.js +++ b/apps/files/l10n/si_LK.js @@ -22,9 +22,9 @@ OC.L10N.register( "Size" : "ප්‍රමාණය", "Modified" : "වෙනස් කළ", "New" : "නව", - "Upload" : "උඩුගත කරන්න", "Text file" : "පෙළ ගොනුව", "Folder" : "ෆෝල්ඩරය", + "Upload" : "උඩුගත කරන්න", "A new file or folder has been created" : "නව ගොනුවක් හෝ බහාලුමක් නිර්මාණය කර ඇත ", "A file or folder has been changed" : "ගොනුවක් හෝ ෆෝල්ඩරයක් වෙනස් වී ඇත", "A file or folder has been deleted" : "ගොනුවක් හෝ ෆෝල්ඩරයක් මකා දමා ඇත", diff --git a/apps/files/l10n/si_LK.json b/apps/files/l10n/si_LK.json index 2f910f1d90b..b46144f4881 100644 --- a/apps/files/l10n/si_LK.json +++ b/apps/files/l10n/si_LK.json @@ -20,9 +20,9 @@ "Size" : "ප්‍රමාණය", "Modified" : "වෙනස් කළ", "New" : "නව", - "Upload" : "උඩුගත කරන්න", "Text file" : "පෙළ ගොනුව", "Folder" : "ෆෝල්ඩරය", + "Upload" : "උඩුගත කරන්න", "A new file or folder has been created" : "නව ගොනුවක් හෝ බහාලුමක් නිර්මාණය කර ඇත ", "A file or folder has been changed" : "ගොනුවක් හෝ ෆෝල්ඩරයක් වෙනස් වී ඇත", "A file or folder has been deleted" : "ගොනුවක් හෝ ෆෝල්ඩරයක් මකා දමා ඇත", diff --git a/apps/files/l10n/sk_SK.js b/apps/files/l10n/sk_SK.js index e2fbf695f81..1736a1f94c1 100644 --- a/apps/files/l10n/sk_SK.js +++ b/apps/files/l10n/sk_SK.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Obľúbené", "Home" : "Domov", "Close" : "Zavrieť", + "Upload cancelled." : "Odosielanie je zrušené.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nemožno nahrať súbor {filename}, pretože je to priečinok, alebo má 0 bitov", "Total file size {size1} exceeds upload limit {size2}" : "Celková veľkosť súboru {size1} prekračuje upload limit {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nie je dostatok voľného miesta, chcete nahrať {size1} ale k dispozíciji je len {size2}", - "Upload cancelled." : "Odosielanie je zrušené.", "Could not get result from server." : "Nepodarilo sa dostať výsledky zo servera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Opustenie stránky zruší práve prebiehajúce odosielanie súboru.", "Actions" : "Akcie", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n bajt","%n bajty","%n bajtov"], "Favorited" : "Pridané k obľúbeným", "Favorite" : "Obľúbené", - "{newname} already exists" : "{newname} už existuje", - "Upload" : "Nahrať", "Text file" : "Textový súbor", "New text file.txt" : "Nový text file.txt", "Folder" : "Priečinok", "New folder" : "Nový priečinok", + "{newname} already exists" : "{newname} už existuje", + "Upload" : "Nahrať", "An error occurred while trying to update the tags" : "Pri pokuse o aktualizáciu štítkov došlo k chybe", "A new file or folder has been created" : "Nový súbor alebo priečinok bol vytvorený", "A file or folder has been changed" : "Súbor alebo priečinok bol zmenený", @@ -102,9 +102,7 @@ OC.L10N.register( "File handling" : "Nastavenie správania sa k súborom", "Maximum upload size" : "Maximálna veľkosť odosielaného súboru", "max. possible: " : "najväčšie možné:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "S PHP-FPM môže trvať do 5 minút, kým sa nastavenie po uložení prejaví.", "Save" : "Uložiť", - "Can not be edited from here due to insufficient permissions." : "Úpravy nie sú možné z dôvodu nedostatočných oprávnení.", "Settings" : "Nastavenia", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Použite túto linku pre prístup k vašim súborom cez WebDAV", diff --git a/apps/files/l10n/sk_SK.json b/apps/files/l10n/sk_SK.json index e5748baa4c8..8936375cade 100644 --- a/apps/files/l10n/sk_SK.json +++ b/apps/files/l10n/sk_SK.json @@ -28,10 +28,10 @@ "Favorites" : "Obľúbené", "Home" : "Domov", "Close" : "Zavrieť", + "Upload cancelled." : "Odosielanie je zrušené.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nemožno nahrať súbor {filename}, pretože je to priečinok, alebo má 0 bitov", "Total file size {size1} exceeds upload limit {size2}" : "Celková veľkosť súboru {size1} prekračuje upload limit {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nie je dostatok voľného miesta, chcete nahrať {size1} ale k dispozíciji je len {size2}", - "Upload cancelled." : "Odosielanie je zrušené.", "Could not get result from server." : "Nepodarilo sa dostať výsledky zo servera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Opustenie stránky zruší práve prebiehajúce odosielanie súboru.", "Actions" : "Akcie", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n bajt","%n bajty","%n bajtov"], "Favorited" : "Pridané k obľúbeným", "Favorite" : "Obľúbené", - "{newname} already exists" : "{newname} už existuje", - "Upload" : "Nahrať", "Text file" : "Textový súbor", "New text file.txt" : "Nový text file.txt", "Folder" : "Priečinok", "New folder" : "Nový priečinok", + "{newname} already exists" : "{newname} už existuje", + "Upload" : "Nahrať", "An error occurred while trying to update the tags" : "Pri pokuse o aktualizáciu štítkov došlo k chybe", "A new file or folder has been created" : "Nový súbor alebo priečinok bol vytvorený", "A file or folder has been changed" : "Súbor alebo priečinok bol zmenený", @@ -100,9 +100,7 @@ "File handling" : "Nastavenie správania sa k súborom", "Maximum upload size" : "Maximálna veľkosť odosielaného súboru", "max. possible: " : "najväčšie možné:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "S PHP-FPM môže trvať do 5 minút, kým sa nastavenie po uložení prejaví.", "Save" : "Uložiť", - "Can not be edited from here due to insufficient permissions." : "Úpravy nie sú možné z dôvodu nedostatočných oprávnení.", "Settings" : "Nastavenia", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Použite túto linku pre prístup k vašim súborom cez WebDAV", diff --git a/apps/files/l10n/sl.js b/apps/files/l10n/sl.js index 7ce39724a98..d89d31f6aea 100644 --- a/apps/files/l10n/sl.js +++ b/apps/files/l10n/sl.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Priljubljene", "Home" : "Domači naslov", "Close" : "Zapri", + "Upload cancelled." : "Pošiljanje je preklicano.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ni mogoče poslati datoteke {filename}, saj je to ali mapa ali pa je velikost datoteke 0 bajtov.", "Total file size {size1} exceeds upload limit {size2}" : "Skupna velikost {size1} presega omejitev velikosti {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Na voljo ni dovolj prostora. Velikost poslane datoteke je {size1}, na voljo pa je je {size2}.", - "Upload cancelled." : "Pošiljanje je preklicano.", "Could not get result from server." : "Ni mogoče pridobiti podatkov s strežnika.", "File upload is in progress. Leaving the page now will cancel the upload." : "V teku je pošiljanje datoteke. Če zapustite to stran zdaj, bo pošiljanje preklicano.", "Actions" : "Dejanja", @@ -71,10 +71,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["se sklada s filtrom '{filter}'","se skladata s filtrom '{filter}'","se skladajo s filtrom '{filter}'","se skladajo s filtrom '{filter}'"], "Favorited" : "Označeno kot priljubljeno", "Favorite" : "Priljubljene", - "Upload" : "Pošlji", "Text file" : "Besedilna datoteka", "Folder" : "Mapa", "New folder" : "Nova mapa", + "Upload" : "Pošlji", "An error occurred while trying to update the tags" : "Prišlo je do napake med posodabljanjem oznak", "A new file or folder has been created" : "Nova datoteka ali mapa je ustvarjena", "A file or folder has been changed" : "Datoteka ali mapa je spremenjena.", @@ -97,7 +97,6 @@ OC.L10N.register( "Maximum upload size" : "Največja velikost za pošiljanja", "max. possible: " : "največ mogoče:", "Save" : "Shrani", - "Can not be edited from here due to insufficient permissions." : "Predmeta ni mogoče urejati zaradi neustreznih dovoljenj.", "Settings" : "Nastavitve", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Uporabite naslov za dostop do datotek peko sistema WebDAV.", diff --git a/apps/files/l10n/sl.json b/apps/files/l10n/sl.json index b4b28f95bf1..6dbbd99371a 100644 --- a/apps/files/l10n/sl.json +++ b/apps/files/l10n/sl.json @@ -28,10 +28,10 @@ "Favorites" : "Priljubljene", "Home" : "Domači naslov", "Close" : "Zapri", + "Upload cancelled." : "Pošiljanje je preklicano.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ni mogoče poslati datoteke {filename}, saj je to ali mapa ali pa je velikost datoteke 0 bajtov.", "Total file size {size1} exceeds upload limit {size2}" : "Skupna velikost {size1} presega omejitev velikosti {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Na voljo ni dovolj prostora. Velikost poslane datoteke je {size1}, na voljo pa je je {size2}.", - "Upload cancelled." : "Pošiljanje je preklicano.", "Could not get result from server." : "Ni mogoče pridobiti podatkov s strežnika.", "File upload is in progress. Leaving the page now will cancel the upload." : "V teku je pošiljanje datoteke. Če zapustite to stran zdaj, bo pošiljanje preklicano.", "Actions" : "Dejanja", @@ -69,10 +69,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["se sklada s filtrom '{filter}'","se skladata s filtrom '{filter}'","se skladajo s filtrom '{filter}'","se skladajo s filtrom '{filter}'"], "Favorited" : "Označeno kot priljubljeno", "Favorite" : "Priljubljene", - "Upload" : "Pošlji", "Text file" : "Besedilna datoteka", "Folder" : "Mapa", "New folder" : "Nova mapa", + "Upload" : "Pošlji", "An error occurred while trying to update the tags" : "Prišlo je do napake med posodabljanjem oznak", "A new file or folder has been created" : "Nova datoteka ali mapa je ustvarjena", "A file or folder has been changed" : "Datoteka ali mapa je spremenjena.", @@ -95,7 +95,6 @@ "Maximum upload size" : "Največja velikost za pošiljanja", "max. possible: " : "največ mogoče:", "Save" : "Shrani", - "Can not be edited from here due to insufficient permissions." : "Predmeta ni mogoče urejati zaradi neustreznih dovoljenj.", "Settings" : "Nastavitve", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Uporabite naslov za dostop do datotek peko sistema WebDAV.", diff --git a/apps/files/l10n/sq.js b/apps/files/l10n/sq.js index 8f19800cd2a..9428855d9ee 100644 --- a/apps/files/l10n/sq.js +++ b/apps/files/l10n/sq.js @@ -74,12 +74,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n bajt","%n bajte"], "Favorited" : "U kalua e parapëlqyer", "Favorite" : "E parapëlqyer", - "{newname} already exists" : "Ka tashmë një {newname}", - "Upload" : "Ngarkoje", "Text file" : "Kartelë tekst", "New text file.txt" : "Kartelë e re file.txt", "Folder" : "Dosje", "New folder" : "Dosje e re", + "{newname} already exists" : "Ka tashmë një {newname}", + "Upload" : "Ngarkoje", "An error occurred while trying to update the tags" : "Ndodhi një gabim teksa provohej të përditësoheshin etiketat", "A new file or folder has been created" : "U krijua një kartelë ose dosje e re", "A file or folder has been changed" : "U ndryshua një kartelë ose dosje", @@ -104,9 +104,7 @@ OC.L10N.register( "File handling" : "Trajtim kartele", "Maximum upload size" : "Madhësi maksimale ngarkimi", "max. possible: " : "maks. i mundshëm: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Me PHP-FPM kjo vlerë mund të dojë deri në 5 minuta të hyjë në fuqi, pasi të ruhet.", "Save" : "Ruaje", - "Can not be edited from here due to insufficient permissions." : "S’mund të përpunohet që këtu, për shkak lejesh të pamjaftueshme.", "Settings" : "Rregullime", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Përdorni këtë adresë për të hyrë te Kartelat tuaja përmes WebDAV-it", diff --git a/apps/files/l10n/sq.json b/apps/files/l10n/sq.json index 462f4d06392..65e87f42c1b 100644 --- a/apps/files/l10n/sq.json +++ b/apps/files/l10n/sq.json @@ -72,12 +72,12 @@ "_%n byte_::_%n bytes_" : ["%n bajt","%n bajte"], "Favorited" : "U kalua e parapëlqyer", "Favorite" : "E parapëlqyer", - "{newname} already exists" : "Ka tashmë një {newname}", - "Upload" : "Ngarkoje", "Text file" : "Kartelë tekst", "New text file.txt" : "Kartelë e re file.txt", "Folder" : "Dosje", "New folder" : "Dosje e re", + "{newname} already exists" : "Ka tashmë një {newname}", + "Upload" : "Ngarkoje", "An error occurred while trying to update the tags" : "Ndodhi një gabim teksa provohej të përditësoheshin etiketat", "A new file or folder has been created" : "U krijua një kartelë ose dosje e re", "A file or folder has been changed" : "U ndryshua një kartelë ose dosje", @@ -102,9 +102,7 @@ "File handling" : "Trajtim kartele", "Maximum upload size" : "Madhësi maksimale ngarkimi", "max. possible: " : "maks. i mundshëm: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Me PHP-FPM kjo vlerë mund të dojë deri në 5 minuta të hyjë në fuqi, pasi të ruhet.", "Save" : "Ruaje", - "Can not be edited from here due to insufficient permissions." : "S’mund të përpunohet që këtu, për shkak lejesh të pamjaftueshme.", "Settings" : "Rregullime", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Përdorni këtë adresë për të hyrë te Kartelat tuaja përmes WebDAV-it", diff --git a/apps/files/l10n/sr.js b/apps/files/l10n/sr.js index 93f8979c2cb..289b7dd432c 100644 --- a/apps/files/l10n/sr.js +++ b/apps/files/l10n/sr.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Омиљени", "Home" : "Почетна", "Close" : "Затвори", + "Upload cancelled." : "Отпремање је отказано.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Не могу да отпремим {filename} јер је то директоријум или има 0 бајтова", "Total file size {size1} exceeds upload limit {size2}" : "Величина {size1} превазилази ограничење за отпремање од {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Нема простора. Отпремате {size1} али само {size2} је преостало", - "Upload cancelled." : "Отпремање је отказано.", "Could not get result from server." : "Не могу да добијем резултат са сервера.", "File upload is in progress. Leaving the page now will cancel the upload." : "Отпремање фајла је у току. Ако сада напустите страницу, отказаћете отпремање.", "Actions" : "Радње", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n бајт","%n бајта","%n бајта"], "Favorited" : "Омиљено", "Favorite" : "Омиљени", - "{newname} already exists" : "{newname} већ постоји", - "Upload" : "Отпреми", "Text file" : "текстуални фајл", "New text file.txt" : "Нов текстуални фајл.txt", "Folder" : "фасцикла", "New folder" : "Нова фасцикла", + "{newname} already exists" : "{newname} већ постоји", + "Upload" : "Отпреми", "An error occurred while trying to update the tags" : "Дошло је до грешке при покушају ажурирања ознака", "A new file or folder has been created" : "Нови фајл или фасцикла су направљени", "A file or folder has been changed" : "Фајл или фасцикла су измењени", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Руковање фајловима", "Maximum upload size" : "Највећа величина отпремања", "max. possible: " : "највише могуће:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "У PHP-FPM-у ова вредност има ефекта тек након 5 минута након примене.", "Save" : "Сачувај", - "Can not be edited from here due to insufficient permissions." : "Не може да се мења одавде због недостатка дозвола.", "Settings" : "Поставке", "WebDAV" : "ВебДАВ", "Use this address to access your Files via WebDAV" : "Користите ову адресу да приступите фајловима преко ВебДАВ-а", diff --git a/apps/files/l10n/sr.json b/apps/files/l10n/sr.json index 08ba9712de7..60457925962 100644 --- a/apps/files/l10n/sr.json +++ b/apps/files/l10n/sr.json @@ -28,10 +28,10 @@ "Favorites" : "Омиљени", "Home" : "Почетна", "Close" : "Затвори", + "Upload cancelled." : "Отпремање је отказано.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Не могу да отпремим {filename} јер је то директоријум или има 0 бајтова", "Total file size {size1} exceeds upload limit {size2}" : "Величина {size1} превазилази ограничење за отпремање од {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Нема простора. Отпремате {size1} али само {size2} је преостало", - "Upload cancelled." : "Отпремање је отказано.", "Could not get result from server." : "Не могу да добијем резултат са сервера.", "File upload is in progress. Leaving the page now will cancel the upload." : "Отпремање фајла је у току. Ако сада напустите страницу, отказаћете отпремање.", "Actions" : "Радње", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n бајт","%n бајта","%n бајта"], "Favorited" : "Омиљено", "Favorite" : "Омиљени", - "{newname} already exists" : "{newname} већ постоји", - "Upload" : "Отпреми", "Text file" : "текстуални фајл", "New text file.txt" : "Нов текстуални фајл.txt", "Folder" : "фасцикла", "New folder" : "Нова фасцикла", + "{newname} already exists" : "{newname} већ постоји", + "Upload" : "Отпреми", "An error occurred while trying to update the tags" : "Дошло је до грешке при покушају ажурирања ознака", "A new file or folder has been created" : "Нови фајл или фасцикла су направљени", "A file or folder has been changed" : "Фајл или фасцикла су измењени", @@ -103,9 +103,7 @@ "File handling" : "Руковање фајловима", "Maximum upload size" : "Највећа величина отпремања", "max. possible: " : "највише могуће:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "У PHP-FPM-у ова вредност има ефекта тек након 5 минута након примене.", "Save" : "Сачувај", - "Can not be edited from here due to insufficient permissions." : "Не може да се мења одавде због недостатка дозвола.", "Settings" : "Поставке", "WebDAV" : "ВебДАВ", "Use this address to access your Files via WebDAV" : "Користите ову адресу да приступите фајловима преко ВебДАВ-а", diff --git a/apps/files/l10n/sr@latin.js b/apps/files/l10n/sr@latin.js index 9c7732e4e71..2907018adfb 100644 --- a/apps/files/l10n/sr@latin.js +++ b/apps/files/l10n/sr@latin.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Omiljeni", "Home" : "Početna", "Close" : "Zatvori", + "Upload cancelled." : "Otpremanje je otkazano.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ne mogu da otpremim {filename} jer je to direktorijum ili ima 0 bajtova", "Total file size {size1} exceeds upload limit {size2}" : "Veličina {size1} prevazilazi ograničenje za otpremanje od {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nema prostora. Otpremate {size1} ali samo {size2} je preostalo", - "Upload cancelled." : "Otpremanje je otkazano.", "Could not get result from server." : "Ne mogu da dobijem rezultat sa servera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Otpremanje fajla je u toku. Ako sada napustite stranicu, otkazaćete otpremanje.", "Download" : "Preuzmi", @@ -68,10 +68,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["se poklapa sa '{filter}'","se poklapaju sa '{filter}'","se poklapa sa '{filter}'"], "Favorited" : "Omiljeno", "Favorite" : "Omiljeni", - "Upload" : "Otpremi", "Text file" : "tekstualni fajl", "Folder" : "fascikla", "New folder" : "Nova fascikla", + "Upload" : "Otpremi", "An error occurred while trying to update the tags" : "Došlo je do greške pri pokušaju ažuriranja oznaka", "A new file or folder has been created" : "Novi fajl ili fascikla su napravljeni", "A file or folder has been changed" : "Fajl ili fascikla su izmenjeni", @@ -94,7 +94,6 @@ OC.L10N.register( "Maximum upload size" : "Najveća veličina otpremanja", "max. possible: " : "najviše moguće:", "Save" : "Sačuvaj", - "Can not be edited from here due to insufficient permissions." : "Ne može da se menja odavde zbog nedostatka dozvola.", "Settings" : "Postavke", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Koristite ovu adresu da pristupite fajlovima preko WebDAV-a", diff --git a/apps/files/l10n/sr@latin.json b/apps/files/l10n/sr@latin.json index 0eb117e6026..7026569e117 100644 --- a/apps/files/l10n/sr@latin.json +++ b/apps/files/l10n/sr@latin.json @@ -28,10 +28,10 @@ "Favorites" : "Omiljeni", "Home" : "Početna", "Close" : "Zatvori", + "Upload cancelled." : "Otpremanje je otkazano.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Ne mogu da otpremim {filename} jer je to direktorijum ili ima 0 bajtova", "Total file size {size1} exceeds upload limit {size2}" : "Veličina {size1} prevazilazi ograničenje za otpremanje od {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nema prostora. Otpremate {size1} ali samo {size2} je preostalo", - "Upload cancelled." : "Otpremanje je otkazano.", "Could not get result from server." : "Ne mogu da dobijem rezultat sa servera.", "File upload is in progress. Leaving the page now will cancel the upload." : "Otpremanje fajla je u toku. Ako sada napustite stranicu, otkazaćete otpremanje.", "Download" : "Preuzmi", @@ -66,10 +66,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["se poklapa sa '{filter}'","se poklapaju sa '{filter}'","se poklapa sa '{filter}'"], "Favorited" : "Omiljeno", "Favorite" : "Omiljeni", - "Upload" : "Otpremi", "Text file" : "tekstualni fajl", "Folder" : "fascikla", "New folder" : "Nova fascikla", + "Upload" : "Otpremi", "An error occurred while trying to update the tags" : "Došlo je do greške pri pokušaju ažuriranja oznaka", "A new file or folder has been created" : "Novi fajl ili fascikla su napravljeni", "A file or folder has been changed" : "Fajl ili fascikla su izmenjeni", @@ -92,7 +92,6 @@ "Maximum upload size" : "Najveća veličina otpremanja", "max. possible: " : "najviše moguće:", "Save" : "Sačuvaj", - "Can not be edited from here due to insufficient permissions." : "Ne može da se menja odavde zbog nedostatka dozvola.", "Settings" : "Postavke", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Koristite ovu adresu da pristupite fajlovima preko WebDAV-a", diff --git a/apps/files/l10n/sv.js b/apps/files/l10n/sv.js index 19f42fb144b..58f6d76c29e 100644 --- a/apps/files/l10n/sv.js +++ b/apps/files/l10n/sv.js @@ -73,12 +73,12 @@ OC.L10N.register( "Path" : "sökväg", "Favorited" : "Favoritiserad", "Favorite" : "Favorit", - "{newname} already exists" : "{newname} existerar redan", - "Upload" : "Ladda upp", "Text file" : "Textfil", "New text file.txt" : "nytextfil.txt", "Folder" : "Mapp", "New folder" : "Ny mapp", + "{newname} already exists" : "{newname} existerar redan", + "Upload" : "Ladda upp", "An error occurred while trying to update the tags" : "Ett fel uppstod när uppdatera taggarna", "A new file or folder has been created" : "En ny fil eller mapp har blivit skapad", "A file or folder has been changed" : "En ny fil eller mapp har blivit ändrad", @@ -102,9 +102,7 @@ OC.L10N.register( "File handling" : "Filhantering", "Maximum upload size" : "Maximal storlek att ladda upp", "max. possible: " : "max. möjligt:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Med PHP-FPM detta värde kan ta upp till 5 minuter för att träda i kraft efter att ha sparat.", "Save" : "Spara", - "Can not be edited from here due to insufficient permissions." : "Kan inte redigeras härifrån på grund av otillräcklig behörighet.", "Settings" : "Inställningar", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Använd denna adress till nå dina Filer via WebDAV", diff --git a/apps/files/l10n/sv.json b/apps/files/l10n/sv.json index ea512d4f54b..35faa25d1a0 100644 --- a/apps/files/l10n/sv.json +++ b/apps/files/l10n/sv.json @@ -71,12 +71,12 @@ "Path" : "sökväg", "Favorited" : "Favoritiserad", "Favorite" : "Favorit", - "{newname} already exists" : "{newname} existerar redan", - "Upload" : "Ladda upp", "Text file" : "Textfil", "New text file.txt" : "nytextfil.txt", "Folder" : "Mapp", "New folder" : "Ny mapp", + "{newname} already exists" : "{newname} existerar redan", + "Upload" : "Ladda upp", "An error occurred while trying to update the tags" : "Ett fel uppstod när uppdatera taggarna", "A new file or folder has been created" : "En ny fil eller mapp har blivit skapad", "A file or folder has been changed" : "En ny fil eller mapp har blivit ändrad", @@ -100,9 +100,7 @@ "File handling" : "Filhantering", "Maximum upload size" : "Maximal storlek att ladda upp", "max. possible: " : "max. möjligt:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "Med PHP-FPM detta värde kan ta upp till 5 minuter för att träda i kraft efter att ha sparat.", "Save" : "Spara", - "Can not be edited from here due to insufficient permissions." : "Kan inte redigeras härifrån på grund av otillräcklig behörighet.", "Settings" : "Inställningar", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Använd denna adress till nå dina Filer via WebDAV", diff --git a/apps/files/l10n/ta_IN.js b/apps/files/l10n/ta_IN.js index 85ed1ea3141..b2371916f12 100644 --- a/apps/files/l10n/ta_IN.js +++ b/apps/files/l10n/ta_IN.js @@ -3,8 +3,8 @@ OC.L10N.register( { "Files" : "கோப்புகள்", "Details" : "விவரங்கள்", - "Upload" : "பதிவேற்று", "New folder" : "புதிய கோப்புறை", + "Upload" : "பதிவேற்று", "A new file or folder has been created" : "ஒரு புதிய கோப்புறை அல்லது ஆவணம் உருவாக்கப்பட்டுள்ளது.", "A file or folder has been changed" : "ஒரு கோப்புறை அல்லது ஆவணம் மாற்றம் செய்யப்பட்டுள்ளது.", "A file or folder has been deleted" : "ஒரு கோப்புறை அல்லது ஆவணம் நீக்கப்பட்டுள்ளது. ", diff --git a/apps/files/l10n/ta_IN.json b/apps/files/l10n/ta_IN.json index bb7117bc62e..e5fe6f3fc88 100644 --- a/apps/files/l10n/ta_IN.json +++ b/apps/files/l10n/ta_IN.json @@ -1,8 +1,8 @@ { "translations": { "Files" : "கோப்புகள்", "Details" : "விவரங்கள்", - "Upload" : "பதிவேற்று", "New folder" : "புதிய கோப்புறை", + "Upload" : "பதிவேற்று", "A new file or folder has been created" : "ஒரு புதிய கோப்புறை அல்லது ஆவணம் உருவாக்கப்பட்டுள்ளது.", "A file or folder has been changed" : "ஒரு கோப்புறை அல்லது ஆவணம் மாற்றம் செய்யப்பட்டுள்ளது.", "A file or folder has been deleted" : "ஒரு கோப்புறை அல்லது ஆவணம் நீக்கப்பட்டுள்ளது. ", diff --git a/apps/files/l10n/ta_LK.js b/apps/files/l10n/ta_LK.js index de912eaea2e..3b287a94725 100644 --- a/apps/files/l10n/ta_LK.js +++ b/apps/files/l10n/ta_LK.js @@ -28,9 +28,9 @@ OC.L10N.register( "Modified" : "மாற்றப்பட்டது", "New" : "புதிய", "Favorite" : "விருப்பமான", - "Upload" : "பதிவேற்றுக", "Text file" : "கோப்பு உரை", "Folder" : "கோப்புறை", + "Upload" : "பதிவேற்றுக", "File handling" : "கோப்பு கையாளுதல்", "Maximum upload size" : "பதிவேற்றக்கூடிய ஆகக்கூடிய அளவு ", "max. possible: " : "ஆகக் கூடியது:", diff --git a/apps/files/l10n/ta_LK.json b/apps/files/l10n/ta_LK.json index b14853b503e..8da783d48d3 100644 --- a/apps/files/l10n/ta_LK.json +++ b/apps/files/l10n/ta_LK.json @@ -26,9 +26,9 @@ "Modified" : "மாற்றப்பட்டது", "New" : "புதிய", "Favorite" : "விருப்பமான", - "Upload" : "பதிவேற்றுக", "Text file" : "கோப்பு உரை", "Folder" : "கோப்புறை", + "Upload" : "பதிவேற்றுக", "File handling" : "கோப்பு கையாளுதல்", "Maximum upload size" : "பதிவேற்றக்கூடிய ஆகக்கூடிய அளவு ", "max. possible: " : "ஆகக் கூடியது:", diff --git a/apps/files/l10n/th_TH.js b/apps/files/l10n/th_TH.js index 1cee4efd362..1194c11ced1 100644 --- a/apps/files/l10n/th_TH.js +++ b/apps/files/l10n/th_TH.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "รายการโปรด", "Home" : "บ้าน", "Close" : "ปิด", + "Upload cancelled." : "การอัพโหลดถูกยกเลิก", "Unable to upload {filename} as it is a directory or has 0 bytes" : "ไม่สามารถอัพโหลด {filename} มันเป็นไดเรกทอรีหรือมี 0 ไบต์", "Total file size {size1} exceeds upload limit {size2}" : "ขนาดไฟล์ {size1} ทั้งหมดเกินขีดจำกัด ของการอัพโหลด {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "พื้นที่ว่างไม่เพียงพอคุณจะอัพโหลด {size1} แต่มีพืนที่แค่ {size2}", - "Upload cancelled." : "การอัพโหลดถูกยกเลิก", "Could not get result from server." : "ไม่สามารถรับผลลัพธ์จากเซิร์ฟเวอร์", "File upload is in progress. Leaving the page now will cancel the upload." : "การอัพโหลดไฟล์กำลังอยู่ในระหว่างดำเนินการ การออกจากหน้าเว็บนี้จะทำให้การอัพโหลดถูกยกเลิก", "Actions" : "การกระทำ", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n ไบต์"], "Favorited" : "รายการโปรด", "Favorite" : "รายการโปรด", - "{newname} already exists" : "{newname} ถูกใช้ไปแล้ว", - "Upload" : "อัพโหลด", "Text file" : "ไฟล์ข้อความ", "New text file.txt" : "ไฟล์ข้อความใหม่ .txt", "Folder" : "แฟ้มเอกสาร", "New folder" : "โฟลเดอร์ใหม่", + "{newname} already exists" : "{newname} ถูกใช้ไปแล้ว", + "Upload" : "อัพโหลด", "An error occurred while trying to update the tags" : "เกิดข้อผิดพลาดขณะที่พยายามจะปรับปรุงแท็ก", "A new file or folder has been created" : "มีไฟล์ใหม่หรือโฟลเดอร์ได้ถูก สร้างขึ้น!", "A file or folder has been changed" : "มีไฟล์หรือโฟลเดอร์ได้ถูก เปลี่ยน!", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "การจัดการไฟล์", "Maximum upload size" : "ขนาดไฟล์สูงสุดที่อัพโหลดได้", "max. possible: " : "จำนวนสูงสุดที่สามารถทำได้: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "ด้วยค่า PHP-FPM นี้อาจใช้เวลาถึง 5 นาที จะมีผลหลังจากการบันทึก", "Save" : "บันทึก", - "Can not be edited from here due to insufficient permissions." : "ไม่สามารถแก้ไขได้จากที่นี่เนื่องจากสิทธิ์ไม่เพียงพอ", "Settings" : "ตั้งค่า", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "ใช้ที่อยู่นี้เพื่อ เข้าถึงไฟล์ของคุณผ่าน WebDAV", diff --git a/apps/files/l10n/th_TH.json b/apps/files/l10n/th_TH.json index e15e4e5803b..80f80e54ddf 100644 --- a/apps/files/l10n/th_TH.json +++ b/apps/files/l10n/th_TH.json @@ -28,10 +28,10 @@ "Favorites" : "รายการโปรด", "Home" : "บ้าน", "Close" : "ปิด", + "Upload cancelled." : "การอัพโหลดถูกยกเลิก", "Unable to upload {filename} as it is a directory or has 0 bytes" : "ไม่สามารถอัพโหลด {filename} มันเป็นไดเรกทอรีหรือมี 0 ไบต์", "Total file size {size1} exceeds upload limit {size2}" : "ขนาดไฟล์ {size1} ทั้งหมดเกินขีดจำกัด ของการอัพโหลด {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "พื้นที่ว่างไม่เพียงพอคุณจะอัพโหลด {size1} แต่มีพืนที่แค่ {size2}", - "Upload cancelled." : "การอัพโหลดถูกยกเลิก", "Could not get result from server." : "ไม่สามารถรับผลลัพธ์จากเซิร์ฟเวอร์", "File upload is in progress. Leaving the page now will cancel the upload." : "การอัพโหลดไฟล์กำลังอยู่ในระหว่างดำเนินการ การออกจากหน้าเว็บนี้จะทำให้การอัพโหลดถูกยกเลิก", "Actions" : "การกระทำ", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n ไบต์"], "Favorited" : "รายการโปรด", "Favorite" : "รายการโปรด", - "{newname} already exists" : "{newname} ถูกใช้ไปแล้ว", - "Upload" : "อัพโหลด", "Text file" : "ไฟล์ข้อความ", "New text file.txt" : "ไฟล์ข้อความใหม่ .txt", "Folder" : "แฟ้มเอกสาร", "New folder" : "โฟลเดอร์ใหม่", + "{newname} already exists" : "{newname} ถูกใช้ไปแล้ว", + "Upload" : "อัพโหลด", "An error occurred while trying to update the tags" : "เกิดข้อผิดพลาดขณะที่พยายามจะปรับปรุงแท็ก", "A new file or folder has been created" : "มีไฟล์ใหม่หรือโฟลเดอร์ได้ถูก สร้างขึ้น!", "A file or folder has been changed" : "มีไฟล์หรือโฟลเดอร์ได้ถูก เปลี่ยน!", @@ -103,9 +103,7 @@ "File handling" : "การจัดการไฟล์", "Maximum upload size" : "ขนาดไฟล์สูงสุดที่อัพโหลดได้", "max. possible: " : "จำนวนสูงสุดที่สามารถทำได้: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "ด้วยค่า PHP-FPM นี้อาจใช้เวลาถึง 5 นาที จะมีผลหลังจากการบันทึก", "Save" : "บันทึก", - "Can not be edited from here due to insufficient permissions." : "ไม่สามารถแก้ไขได้จากที่นี่เนื่องจากสิทธิ์ไม่เพียงพอ", "Settings" : "ตั้งค่า", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "ใช้ที่อยู่นี้เพื่อ เข้าถึงไฟล์ของคุณผ่าน WebDAV", diff --git a/apps/files/l10n/tr.js b/apps/files/l10n/tr.js index cd48408b9e1..b2c4fd56df9 100644 --- a/apps/files/l10n/tr.js +++ b/apps/files/l10n/tr.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Sık kullanılanlar", "Home" : "Ev", "Close" : "Kapat", + "Upload cancelled." : "Yükleme iptal edildi.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "{filename} bir dizin veya 0 bayt olduğundan yüklenemedi", "Total file size {size1} exceeds upload limit {size2}" : "Toplam dosya boyutu {size1}, {size2} gönderme sınırını aşıyor", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Yeterince boş alan yok. Gönderdiğiniz boyut {size1} ancak {size2} alan mevcut", - "Upload cancelled." : "Yükleme iptal edildi.", "Could not get result from server." : "Sunucudan sonuç alınamadı.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dosya yükleme işlemi sürüyor. Şu anda sayfadan ayrılmak yükleme işlemini iptal edecek.", "Actions" : "Eylemler", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"], "Favorited" : "Sık kullanılanlara eklendi", "Favorite" : "Sık kullanılan", - "{newname} already exists" : "{newname} zaten mevcut", - "Upload" : "Yükle", "Text file" : "Metin dosyası", "New text file.txt" : "Yeni metin dosyası.txt", "Folder" : "Klasör", "New folder" : "Yeni klasör", + "{newname} already exists" : "{newname} zaten mevcut", + "Upload" : "Yükle", "An error occurred while trying to update the tags" : "Etiketler güncellenmeye çalışılırken bir hata oluştu", "A new file or folder has been created" : "Yeni bir dosya veya klasör oluşturuldu", "A file or folder has been changed" : "Bir dosya veya klasör değiştirildi", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "Dosya işlemleri", "Maximum upload size" : "Azami yükleme boyutu", "max. possible: " : "mümkün olan en fazla: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM ile bu değerin kaydedildikten sonra etkili olabilmesi için 5 dakika gerekebilir.", "Save" : "Kaydet", - "Can not be edited from here due to insufficient permissions." : "Yetersiz izinler buradan düzenlenemez.", "Settings" : "Ayarlar", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Dosyalarınıza WebDAV aracılığıyla erişmek için bu adresi kullanın", diff --git a/apps/files/l10n/tr.json b/apps/files/l10n/tr.json index 92af334f703..fcb87d74fa1 100644 --- a/apps/files/l10n/tr.json +++ b/apps/files/l10n/tr.json @@ -28,10 +28,10 @@ "Favorites" : "Sık kullanılanlar", "Home" : "Ev", "Close" : "Kapat", + "Upload cancelled." : "Yükleme iptal edildi.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "{filename} bir dizin veya 0 bayt olduğundan yüklenemedi", "Total file size {size1} exceeds upload limit {size2}" : "Toplam dosya boyutu {size1}, {size2} gönderme sınırını aşıyor", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Yeterince boş alan yok. Gönderdiğiniz boyut {size1} ancak {size2} alan mevcut", - "Upload cancelled." : "Yükleme iptal edildi.", "Could not get result from server." : "Sunucudan sonuç alınamadı.", "File upload is in progress. Leaving the page now will cancel the upload." : "Dosya yükleme işlemi sürüyor. Şu anda sayfadan ayrılmak yükleme işlemini iptal edecek.", "Actions" : "Eylemler", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"], "Favorited" : "Sık kullanılanlara eklendi", "Favorite" : "Sık kullanılan", - "{newname} already exists" : "{newname} zaten mevcut", - "Upload" : "Yükle", "Text file" : "Metin dosyası", "New text file.txt" : "Yeni metin dosyası.txt", "Folder" : "Klasör", "New folder" : "Yeni klasör", + "{newname} already exists" : "{newname} zaten mevcut", + "Upload" : "Yükle", "An error occurred while trying to update the tags" : "Etiketler güncellenmeye çalışılırken bir hata oluştu", "A new file or folder has been created" : "Yeni bir dosya veya klasör oluşturuldu", "A file or folder has been changed" : "Bir dosya veya klasör değiştirildi", @@ -103,9 +103,7 @@ "File handling" : "Dosya işlemleri", "Maximum upload size" : "Azami yükleme boyutu", "max. possible: " : "mümkün olan en fazla: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM ile bu değerin kaydedildikten sonra etkili olabilmesi için 5 dakika gerekebilir.", "Save" : "Kaydet", - "Can not be edited from here due to insufficient permissions." : "Yetersiz izinler buradan düzenlenemez.", "Settings" : "Ayarlar", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Dosyalarınıza WebDAV aracılığıyla erişmek için bu adresi kullanın", diff --git a/apps/files/l10n/ug.js b/apps/files/l10n/ug.js index 4371e15067f..5e179c6e0d1 100644 --- a/apps/files/l10n/ug.js +++ b/apps/files/l10n/ug.js @@ -26,10 +26,10 @@ OC.L10N.register( "Modified" : "ئۆزگەرتكەن", "New" : "يېڭى", "Favorite" : "يىغقۇچ", - "Upload" : "يۈكلە", "Text file" : "تېكىست ھۆججەت", "Folder" : "قىسقۇچ", "New folder" : "يېڭى قىسقۇچ", + "Upload" : "يۈكلە", "Save" : "ساقلا", "Settings" : "تەڭشەكلەر", "WebDAV" : "WebDAV", diff --git a/apps/files/l10n/ug.json b/apps/files/l10n/ug.json index f6a71d8bda6..4a4b06b559e 100644 --- a/apps/files/l10n/ug.json +++ b/apps/files/l10n/ug.json @@ -24,10 +24,10 @@ "Modified" : "ئۆزگەرتكەن", "New" : "يېڭى", "Favorite" : "يىغقۇچ", - "Upload" : "يۈكلە", "Text file" : "تېكىست ھۆججەت", "Folder" : "قىسقۇچ", "New folder" : "يېڭى قىسقۇچ", + "Upload" : "يۈكلە", "Save" : "ساقلا", "Settings" : "تەڭشەكلەر", "WebDAV" : "WebDAV", diff --git a/apps/files/l10n/uk.js b/apps/files/l10n/uk.js index bf5b0f1d456..fc071f58279 100644 --- a/apps/files/l10n/uk.js +++ b/apps/files/l10n/uk.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Улюблені", "Home" : "Домашня адреса", "Close" : "Закрити", + "Upload cancelled." : "Вивантаження скасовано.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Неможливо вивантажити {filename}, оскільки це каталог або файл має розмір 0 байт.", "Total file size {size1} exceeds upload limit {size2}" : "Розмір файлу {size1} перевищує обмеження {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Недостатньо вільного місця, ви вивантажуєте {size1}, а залишилося лише {size2}", - "Upload cancelled." : "Вивантаження скасовано.", "Could not get result from server." : "Не вдалося отримати результат від сервера.", "File upload is in progress. Leaving the page now will cancel the upload." : "Виконується вивантаження файлу. Закриття цієї сторінки приведе до скасування вивантаження.", "Actions" : "Дії", @@ -70,10 +70,10 @@ OC.L10N.register( "_matches '{filter}'_::_match '{filter}'_" : ["знайдено '{filter}'","знайдено '{filter}'","знайдено '{filter}'"], "Favorited" : "Улюблений", "Favorite" : "Улюблений", - "Upload" : "Вивантажити", "Text file" : "Текстовий файл", "Folder" : "Тека", "New folder" : "Нова тека", + "Upload" : "Вивантажити", "An error occurred while trying to update the tags" : "Виникла помилка при спробі оновити мітки", "A new file or folder has been created" : "Новий файл або теку було створено", "A file or folder has been changed" : "Файл або теку було змінено ", @@ -96,7 +96,6 @@ OC.L10N.register( "Maximum upload size" : "Максимальний розмір вивантажень", "max. possible: " : "макс. можливе:", "Save" : "Зберегти", - "Can not be edited from here due to insufficient permissions." : "Неможливо відредагувати тут через брак повноважень.", "Settings" : "Налаштування", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Для доступу до файлів через WebDAV використовуйте це посилання", diff --git a/apps/files/l10n/uk.json b/apps/files/l10n/uk.json index 28d307b55be..651b65df99c 100644 --- a/apps/files/l10n/uk.json +++ b/apps/files/l10n/uk.json @@ -28,10 +28,10 @@ "Favorites" : "Улюблені", "Home" : "Домашня адреса", "Close" : "Закрити", + "Upload cancelled." : "Вивантаження скасовано.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Неможливо вивантажити {filename}, оскільки це каталог або файл має розмір 0 байт.", "Total file size {size1} exceeds upload limit {size2}" : "Розмір файлу {size1} перевищує обмеження {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Недостатньо вільного місця, ви вивантажуєте {size1}, а залишилося лише {size2}", - "Upload cancelled." : "Вивантаження скасовано.", "Could not get result from server." : "Не вдалося отримати результат від сервера.", "File upload is in progress. Leaving the page now will cancel the upload." : "Виконується вивантаження файлу. Закриття цієї сторінки приведе до скасування вивантаження.", "Actions" : "Дії", @@ -68,10 +68,10 @@ "_matches '{filter}'_::_match '{filter}'_" : ["знайдено '{filter}'","знайдено '{filter}'","знайдено '{filter}'"], "Favorited" : "Улюблений", "Favorite" : "Улюблений", - "Upload" : "Вивантажити", "Text file" : "Текстовий файл", "Folder" : "Тека", "New folder" : "Нова тека", + "Upload" : "Вивантажити", "An error occurred while trying to update the tags" : "Виникла помилка при спробі оновити мітки", "A new file or folder has been created" : "Новий файл або теку було створено", "A file or folder has been changed" : "Файл або теку було змінено ", @@ -94,7 +94,6 @@ "Maximum upload size" : "Максимальний розмір вивантажень", "max. possible: " : "макс. можливе:", "Save" : "Зберегти", - "Can not be edited from here due to insufficient permissions." : "Неможливо відредагувати тут через брак повноважень.", "Settings" : "Налаштування", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Для доступу до файлів через WebDAV використовуйте це посилання", diff --git a/apps/files/l10n/vi.js b/apps/files/l10n/vi.js index 2c643e3cfb5..e51ae0b46f3 100644 --- a/apps/files/l10n/vi.js +++ b/apps/files/l10n/vi.js @@ -27,8 +27,8 @@ OC.L10N.register( "Favorites" : "Ưa thích", "Home" : "Nhà", "Close" : "Đóng", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "không thể tải {filename} lên do nó là một thư mục hoặc có kích thước bằng 0 byte", "Upload cancelled." : "Hủy tải lên", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "không thể tải {filename} lên do nó là một thư mục hoặc có kích thước bằng 0 byte", "Could not get result from server." : "Không thể nhận được kết quả từ máy chủ.", "File upload is in progress. Leaving the page now will cancel the upload." : "Tập tin tải lên đang được xử lý. Nếu bạn rời khỏi trang bây giờ sẽ hủy quá trình này.", "Actions" : "Actions", @@ -58,10 +58,10 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "Your storage is full, files can not be updated or synced anymore!", "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "Favorite" : "Ưu thích", - "Upload" : "Tải lên", "Text file" : "Tập tin văn bản", "Folder" : "Thư mục", "New folder" : "Tạo thư mục", + "Upload" : "Tải lên", "%s could not be renamed" : "%s không thể đổi tên", "File handling" : "Xử lý tập tin", "Maximum upload size" : "Kích thước tối đa ", diff --git a/apps/files/l10n/vi.json b/apps/files/l10n/vi.json index ac7a1f3828e..bd6250322de 100644 --- a/apps/files/l10n/vi.json +++ b/apps/files/l10n/vi.json @@ -25,8 +25,8 @@ "Favorites" : "Ưa thích", "Home" : "Nhà", "Close" : "Đóng", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "không thể tải {filename} lên do nó là một thư mục hoặc có kích thước bằng 0 byte", "Upload cancelled." : "Hủy tải lên", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "không thể tải {filename} lên do nó là một thư mục hoặc có kích thước bằng 0 byte", "Could not get result from server." : "Không thể nhận được kết quả từ máy chủ.", "File upload is in progress. Leaving the page now will cancel the upload." : "Tập tin tải lên đang được xử lý. Nếu bạn rời khỏi trang bây giờ sẽ hủy quá trình này.", "Actions" : "Actions", @@ -56,10 +56,10 @@ "Your storage is full, files can not be updated or synced anymore!" : "Your storage is full, files can not be updated or synced anymore!", "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "Favorite" : "Ưu thích", - "Upload" : "Tải lên", "Text file" : "Tập tin văn bản", "Folder" : "Thư mục", "New folder" : "Tạo thư mục", + "Upload" : "Tải lên", "%s could not be renamed" : "%s không thể đổi tên", "File handling" : "Xử lý tập tin", "Maximum upload size" : "Kích thước tối đa ", diff --git a/apps/files/l10n/zh_CN.js b/apps/files/l10n/zh_CN.js index d2b0989e35a..e3f113d82fa 100644 --- a/apps/files/l10n/zh_CN.js +++ b/apps/files/l10n/zh_CN.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "收藏", "Home" : "家庭", "Close" : "关闭", + "Upload cancelled." : "上传已取消", "Unable to upload {filename} as it is a directory or has 0 bytes" : "不能上传文件 {filename} ,由于它是一个目录或者为0字节", "Total file size {size1} exceeds upload limit {size2}" : "总文件大小 {size1} 超过上传限制 {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "没有足够的可用空间,您正在上传 {size1} 的文件但是只有 {size2} 可用。", - "Upload cancelled." : "上传已取消", "Could not get result from server." : "不能从服务器得到结果", "File upload is in progress. Leaving the page now will cancel the upload." : "文件正在上传中。现在离开此页会导致上传动作被取消。", "Actions" : "动作", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n 字节"], "Favorited" : "已收藏", "Favorite" : "收藏", - "{newname} already exists" : "{newname} 已经存在", - "Upload" : "上传", "Text file" : "文本文件", "New text file.txt" : "创建文本文件 .txt", "Folder" : "文件夹", "New folder" : "增加文件夹", + "{newname} already exists" : "{newname} 已经存在", + "Upload" : "上传", "An error occurred while trying to update the tags" : "更新标签时出错", "A new file or folder has been created" : "一个新的文件或文件夹已被创建", "A file or folder has been changed" : "一个文件或文件夹已被修改", @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "文件处理", "Maximum upload size" : "最大上传大小", "max. possible: " : "最大允许: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "对于 PHP-FPM 这个值保存后可能需要长达5分钟才会生效。", "Save" : "保存", - "Can not be edited from here due to insufficient permissions." : "由于权限不足无法在此编辑。", "Settings" : "设置", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "使用这个地址 通过 WebDAV 访问您的文件", diff --git a/apps/files/l10n/zh_CN.json b/apps/files/l10n/zh_CN.json index 6eee0d3a765..177be39683c 100644 --- a/apps/files/l10n/zh_CN.json +++ b/apps/files/l10n/zh_CN.json @@ -28,10 +28,10 @@ "Favorites" : "收藏", "Home" : "家庭", "Close" : "关闭", + "Upload cancelled." : "上传已取消", "Unable to upload {filename} as it is a directory or has 0 bytes" : "不能上传文件 {filename} ,由于它是一个目录或者为0字节", "Total file size {size1} exceeds upload limit {size2}" : "总文件大小 {size1} 超过上传限制 {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "没有足够的可用空间,您正在上传 {size1} 的文件但是只有 {size2} 可用。", - "Upload cancelled." : "上传已取消", "Could not get result from server." : "不能从服务器得到结果", "File upload is in progress. Leaving the page now will cancel the upload." : "文件正在上传中。现在离开此页会导致上传动作被取消。", "Actions" : "动作", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n 字节"], "Favorited" : "已收藏", "Favorite" : "收藏", - "{newname} already exists" : "{newname} 已经存在", - "Upload" : "上传", "Text file" : "文本文件", "New text file.txt" : "创建文本文件 .txt", "Folder" : "文件夹", "New folder" : "增加文件夹", + "{newname} already exists" : "{newname} 已经存在", + "Upload" : "上传", "An error occurred while trying to update the tags" : "更新标签时出错", "A new file or folder has been created" : "一个新的文件或文件夹已被创建", "A file or folder has been changed" : "一个文件或文件夹已被修改", @@ -103,9 +103,7 @@ "File handling" : "文件处理", "Maximum upload size" : "最大上传大小", "max. possible: " : "最大允许: ", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "对于 PHP-FPM 这个值保存后可能需要长达5分钟才会生效。", "Save" : "保存", - "Can not be edited from here due to insufficient permissions." : "由于权限不足无法在此编辑。", "Settings" : "设置", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "使用这个地址 通过 WebDAV 访问您的文件", diff --git a/apps/files/l10n/zh_HK.js b/apps/files/l10n/zh_HK.js index 421ae5dc92a..3a984b345ce 100644 --- a/apps/files/l10n/zh_HK.js +++ b/apps/files/l10n/zh_HK.js @@ -14,9 +14,9 @@ OC.L10N.register( "Size" : "大小", "{dirs} and {files}" : "{dirs} 和 {files}", "New" : "新增", - "Upload" : "上戴", "Folder" : "資料夾", "New folder" : "新資料夾", + "Upload" : "上戴", "A new file or folder has been created" : "新檔案或資料夾已被 新增 ", "A file or folder has been changed" : "檔案或資料夾已被 變成 ", "A file or folder has been deleted" : "新檔案或資料夾已被 刪除 ", diff --git a/apps/files/l10n/zh_HK.json b/apps/files/l10n/zh_HK.json index 3d1af1593bd..8b6572bc376 100644 --- a/apps/files/l10n/zh_HK.json +++ b/apps/files/l10n/zh_HK.json @@ -12,9 +12,9 @@ "Size" : "大小", "{dirs} and {files}" : "{dirs} 和 {files}", "New" : "新增", - "Upload" : "上戴", "Folder" : "資料夾", "New folder" : "新資料夾", + "Upload" : "上戴", "A new file or folder has been created" : "新檔案或資料夾已被 新增 ", "A file or folder has been changed" : "檔案或資料夾已被 變成 ", "A file or folder has been deleted" : "新檔案或資料夾已被 刪除 ", diff --git a/apps/files/l10n/zh_TW.js b/apps/files/l10n/zh_TW.js index 432e167da83..aba0261047a 100644 --- a/apps/files/l10n/zh_TW.js +++ b/apps/files/l10n/zh_TW.js @@ -105,9 +105,7 @@ OC.L10N.register( "File handling" : "檔案處理", "Maximum upload size" : "上傳限制", "max. possible: " : "最大允許:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "如果使用 PHP-FPM ,此設定值需要5分鐘左右才會生效", "Save" : "儲存", - "Can not be edited from here due to insufficient permissions." : "無法在這邊編輯,因為權限不足", "Settings" : "設定", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "使用這個地址來透過 WebDAV 存取檔案", diff --git a/apps/files/l10n/zh_TW.json b/apps/files/l10n/zh_TW.json index b82dbfb1ffe..4e4f7d0a871 100644 --- a/apps/files/l10n/zh_TW.json +++ b/apps/files/l10n/zh_TW.json @@ -103,9 +103,7 @@ "File handling" : "檔案處理", "Maximum upload size" : "上傳限制", "max. possible: " : "最大允許:", - "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "如果使用 PHP-FPM ,此設定值需要5分鐘左右才會生效", "Save" : "儲存", - "Can not be edited from here due to insufficient permissions." : "無法在這邊編輯,因為權限不足", "Settings" : "設定", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "使用這個地址來透過 WebDAV 存取檔案", diff --git a/apps/user_ldap/l10n/cs_CZ.js b/apps/user_ldap/l10n/cs_CZ.js index 77fef537f0a..6aa15ebc918 100644 --- a/apps/user_ldap/l10n/cs_CZ.js +++ b/apps/user_ldap/l10n/cs_CZ.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Nelze automaticky detekovat Base DN, zadejte prosím ručně.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "V zadané Base DN nebyl objekt nalezen. Ověřte.", - "More than 1.000 directory entries available." : "Je dostupných více než 1000 adresářů.", " entries available within the provided Base DN" : "záznamů dostupných v zadané Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Došlo k chybě. Ověře prosím Base DN společně s nastavením připojení a přihlašovacími údaji.", "Do you really want to delete the current Server Configuration?" : "Opravdu si přejete smazat současné nastavení serveru?", diff --git a/apps/user_ldap/l10n/cs_CZ.json b/apps/user_ldap/l10n/cs_CZ.json index b1ffce2e029..a2eae7dae20 100644 --- a/apps/user_ldap/l10n/cs_CZ.json +++ b/apps/user_ldap/l10n/cs_CZ.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Nelze automaticky detekovat Base DN, zadejte prosím ručně.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "V zadané Base DN nebyl objekt nalezen. Ověřte.", - "More than 1.000 directory entries available." : "Je dostupných více než 1000 adresářů.", " entries available within the provided Base DN" : "záznamů dostupných v zadané Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Došlo k chybě. Ověře prosím Base DN společně s nastavením připojení a přihlašovacími údaji.", "Do you really want to delete the current Server Configuration?" : "Opravdu si přejete smazat současné nastavení serveru?", diff --git a/apps/user_ldap/l10n/da.js b/apps/user_ldap/l10n/da.js index 7b9222d3abd..c01d3efa018 100644 --- a/apps/user_ldap/l10n/da.js +++ b/apps/user_ldap/l10n/da.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Kunne ikke registrere Base DN - angiv den venligst manuelt.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Intet objekt fundet i den givne Base DN. Gennemse venligst.", - "More than 1.000 directory entries available." : "Mere end 1.000 opslag tilgængelige", " entries available within the provided Base DN" : "poster tilgængelige inden for det angivne Base DN.", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Der opstod en fejl. Tjek venligst Base DN, såvel som forbindelsesindstillingerne og brugeroplysningerne.", "Do you really want to delete the current Server Configuration?" : "Ønsker du virkelig at slette den nuværende Server Konfiguration?", diff --git a/apps/user_ldap/l10n/da.json b/apps/user_ldap/l10n/da.json index 5c0c3ad1d0c..db61541ef73 100644 --- a/apps/user_ldap/l10n/da.json +++ b/apps/user_ldap/l10n/da.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Kunne ikke registrere Base DN - angiv den venligst manuelt.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Intet objekt fundet i den givne Base DN. Gennemse venligst.", - "More than 1.000 directory entries available." : "Mere end 1.000 opslag tilgængelige", " entries available within the provided Base DN" : "poster tilgængelige inden for det angivne Base DN.", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Der opstod en fejl. Tjek venligst Base DN, såvel som forbindelsesindstillingerne og brugeroplysningerne.", "Do you really want to delete the current Server Configuration?" : "Ønsker du virkelig at slette den nuværende Server Konfiguration?", diff --git a/apps/user_ldap/l10n/de.js b/apps/user_ldap/l10n/de.js index 8a944590c6d..107fd24d802 100644 --- a/apps/user_ldap/l10n/de.js +++ b/apps/user_ldap/l10n/de.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Die Base DN konnte nicht erkannt werden, bitte manuell eingeben.", "{nthServer}. Server" : "{nthServer}. - Server", "No object found in the given Base DN. Please revise." : "Keine Objekte in der Base DN gefunden, bitte überprüfen.", - "More than 1.000 directory entries available." : "Mehr als 1.000 Verzeichniseinträge verfügbar.", " entries available within the provided Base DN" : "Einträge in der Vorgesehenen Base DN verfügbar", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ein Fehler ist aufgetreten. Bitte prüfe die Base DN und auch die Verbindungs- und Anmeldeeinstellungen.", "Do you really want to delete the current Server Configuration?" : "Soll die aktuelle Serverkonfiguration wirklich gelöscht werden?", diff --git a/apps/user_ldap/l10n/de.json b/apps/user_ldap/l10n/de.json index 99fa4b39151..8d30e7d4f2f 100644 --- a/apps/user_ldap/l10n/de.json +++ b/apps/user_ldap/l10n/de.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Die Base DN konnte nicht erkannt werden, bitte manuell eingeben.", "{nthServer}. Server" : "{nthServer}. - Server", "No object found in the given Base DN. Please revise." : "Keine Objekte in der Base DN gefunden, bitte überprüfen.", - "More than 1.000 directory entries available." : "Mehr als 1.000 Verzeichniseinträge verfügbar.", " entries available within the provided Base DN" : "Einträge in der Vorgesehenen Base DN verfügbar", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ein Fehler ist aufgetreten. Bitte prüfe die Base DN und auch die Verbindungs- und Anmeldeeinstellungen.", "Do you really want to delete the current Server Configuration?" : "Soll die aktuelle Serverkonfiguration wirklich gelöscht werden?", diff --git a/apps/user_ldap/l10n/de_DE.js b/apps/user_ldap/l10n/de_DE.js index 5a8903d574a..4ef7b94c361 100644 --- a/apps/user_ldap/l10n/de_DE.js +++ b/apps/user_ldap/l10n/de_DE.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Die Base DN konnte nicht erkannt werden, bitte geben Sie sie manuell ein.", "{nthServer}. Server" : "{nthServer}. - Server", "No object found in the given Base DN. Please revise." : "Keine Objekte in der angegebenen Base DN gefunden, bitte überprüfen.", - "More than 1.000 directory entries available." : "Mehr als 1.000 Verzeichniseinträge verfügbar.", " entries available within the provided Base DN" : "Einträge in der angegebenen Base DN verfügbar", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Es ist ein Fehler aufgetreten. Bitte überprüfen Sie die Base DN wie auch die Verbindungseinstellungen und Anmeldeinformationen.", "Do you really want to delete the current Server Configuration?" : "Soll die aktuelle Serverkonfiguration wirklich gelöscht werden?", diff --git a/apps/user_ldap/l10n/de_DE.json b/apps/user_ldap/l10n/de_DE.json index 0485094c345..c90e39c996b 100644 --- a/apps/user_ldap/l10n/de_DE.json +++ b/apps/user_ldap/l10n/de_DE.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Die Base DN konnte nicht erkannt werden, bitte geben Sie sie manuell ein.", "{nthServer}. Server" : "{nthServer}. - Server", "No object found in the given Base DN. Please revise." : "Keine Objekte in der angegebenen Base DN gefunden, bitte überprüfen.", - "More than 1.000 directory entries available." : "Mehr als 1.000 Verzeichniseinträge verfügbar.", " entries available within the provided Base DN" : "Einträge in der angegebenen Base DN verfügbar", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Es ist ein Fehler aufgetreten. Bitte überprüfen Sie die Base DN wie auch die Verbindungseinstellungen und Anmeldeinformationen.", "Do you really want to delete the current Server Configuration?" : "Soll die aktuelle Serverkonfiguration wirklich gelöscht werden?", diff --git a/apps/user_ldap/l10n/el.js b/apps/user_ldap/l10n/el.js index fc9d96aa61a..d8f825b8288 100644 --- a/apps/user_ldap/l10n/el.js +++ b/apps/user_ldap/l10n/el.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Αδυναμία ανίχνευσης Base DN, παρακαλώ να το εισάγετε χειροκίνητα.", "{nthServer}. Server" : "{nthServer}. Διακομιστής", "No object found in the given Base DN. Please revise." : "Δεν βρέθηκε αντικείμενο στο δηλωθέν Base DN. Παρακαλώ αναθεωρήστε.", - "More than 1.000 directory entries available." : "Περισσότερες από 1.000 εγγραφές καταλόγων διαθέσιμες.", " entries available within the provided Base DN" : "διαθέσιμες καταχωρήσεις εντός του δηλωθέντος ", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Παρουσιάστηκε σφάλμα. Παρακαλούμε ελέγξτε το Base DN καθώς και τις ρυθμίσεις και τα διαπιστευτήρια σύνδεσης.", "Do you really want to delete the current Server Configuration?" : "Θέλετε να διαγράψετε τις τρέχουσες ρυθμίσεις του διακομιστή;", diff --git a/apps/user_ldap/l10n/el.json b/apps/user_ldap/l10n/el.json index bd5924586b6..142ca58d844 100644 --- a/apps/user_ldap/l10n/el.json +++ b/apps/user_ldap/l10n/el.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Αδυναμία ανίχνευσης Base DN, παρακαλώ να το εισάγετε χειροκίνητα.", "{nthServer}. Server" : "{nthServer}. Διακομιστής", "No object found in the given Base DN. Please revise." : "Δεν βρέθηκε αντικείμενο στο δηλωθέν Base DN. Παρακαλώ αναθεωρήστε.", - "More than 1.000 directory entries available." : "Περισσότερες από 1.000 εγγραφές καταλόγων διαθέσιμες.", " entries available within the provided Base DN" : "διαθέσιμες καταχωρήσεις εντός του δηλωθέντος ", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Παρουσιάστηκε σφάλμα. Παρακαλούμε ελέγξτε το Base DN καθώς και τις ρυθμίσεις και τα διαπιστευτήρια σύνδεσης.", "Do you really want to delete the current Server Configuration?" : "Θέλετε να διαγράψετε τις τρέχουσες ρυθμίσεις του διακομιστή;", diff --git a/apps/user_ldap/l10n/en_GB.js b/apps/user_ldap/l10n/en_GB.js index 976e8a7e062..3d3acff70bd 100644 --- a/apps/user_ldap/l10n/en_GB.js +++ b/apps/user_ldap/l10n/en_GB.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Could not detect Base DN, please enter it manually.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "No object found in the given Base DN. Please revise.", - "More than 1.000 directory entries available." : "More than 1,000 directory entries available.", " entries available within the provided Base DN" : " entries available within the provided Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "An error occurred. Please check the Base DN, as well as connection settings and credentials.", "Do you really want to delete the current Server Configuration?" : "Do you really want to delete the current Server Configuration?", diff --git a/apps/user_ldap/l10n/en_GB.json b/apps/user_ldap/l10n/en_GB.json index 8e0212f35ca..606ca9b7922 100644 --- a/apps/user_ldap/l10n/en_GB.json +++ b/apps/user_ldap/l10n/en_GB.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Could not detect Base DN, please enter it manually.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "No object found in the given Base DN. Please revise.", - "More than 1.000 directory entries available." : "More than 1,000 directory entries available.", " entries available within the provided Base DN" : " entries available within the provided Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "An error occurred. Please check the Base DN, as well as connection settings and credentials.", "Do you really want to delete the current Server Configuration?" : "Do you really want to delete the current Server Configuration?", diff --git a/apps/user_ldap/l10n/es.js b/apps/user_ldap/l10n/es.js index 5171628428d..bfe48c28f99 100644 --- a/apps/user_ldap/l10n/es.js +++ b/apps/user_ldap/l10n/es.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "No se pudo detectar Base DN, por favor ingrésela manualmente.", "{nthServer}. Server" : "{nthServer}. servidor", "No object found in the given Base DN. Please revise." : "No se encuentra ningún objeto en la Base DN dada. Por favor revisar.", - "More than 1.000 directory entries available." : "Más de 1.000 directorios disponibles.", " entries available within the provided Base DN" : "entradas disponibles dentro de la BaseDN provista", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Un error ocurrió. Por favor revise la Base DN, también como la configuración de la conexión y credenciales.", "Do you really want to delete the current Server Configuration?" : "¿Realmente desea eliminar la configuración actual del servidor?", diff --git a/apps/user_ldap/l10n/es.json b/apps/user_ldap/l10n/es.json index 8a896a9bda2..c8d64f6b9d6 100644 --- a/apps/user_ldap/l10n/es.json +++ b/apps/user_ldap/l10n/es.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "No se pudo detectar Base DN, por favor ingrésela manualmente.", "{nthServer}. Server" : "{nthServer}. servidor", "No object found in the given Base DN. Please revise." : "No se encuentra ningún objeto en la Base DN dada. Por favor revisar.", - "More than 1.000 directory entries available." : "Más de 1.000 directorios disponibles.", " entries available within the provided Base DN" : "entradas disponibles dentro de la BaseDN provista", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Un error ocurrió. Por favor revise la Base DN, también como la configuración de la conexión y credenciales.", "Do you really want to delete the current Server Configuration?" : "¿Realmente desea eliminar la configuración actual del servidor?", diff --git a/apps/user_ldap/l10n/et_EE.js b/apps/user_ldap/l10n/et_EE.js index 1fc38d62d9d..aa0727c9bc1 100644 --- a/apps/user_ldap/l10n/et_EE.js +++ b/apps/user_ldap/l10n/et_EE.js @@ -19,7 +19,6 @@ OC.L10N.register( "Select object classes" : "Vali objekti klassid", "Please check the credentials, they seem to be wrong." : "Palu nkontrolli kasutajaandmeid, need näivad olevat valed.", "{nthServer}. Server" : "{nthServer}. Server", - "More than 1.000 directory entries available." : "Saadaval on rohkem kui 1000 kataloogi sissekannet.", "Do you really want to delete the current Server Configuration?" : "Oled kindel, et tahad kustutada praegust serveri seadistust?", "Confirm Deletion" : "Kinnita kustutamine", "Mode switch" : "Režiimi lüliti", diff --git a/apps/user_ldap/l10n/et_EE.json b/apps/user_ldap/l10n/et_EE.json index 46c7de96524..5d8fbe2f81b 100644 --- a/apps/user_ldap/l10n/et_EE.json +++ b/apps/user_ldap/l10n/et_EE.json @@ -17,7 +17,6 @@ "Select object classes" : "Vali objekti klassid", "Please check the credentials, they seem to be wrong." : "Palu nkontrolli kasutajaandmeid, need näivad olevat valed.", "{nthServer}. Server" : "{nthServer}. Server", - "More than 1.000 directory entries available." : "Saadaval on rohkem kui 1000 kataloogi sissekannet.", "Do you really want to delete the current Server Configuration?" : "Oled kindel, et tahad kustutada praegust serveri seadistust?", "Confirm Deletion" : "Kinnita kustutamine", "Mode switch" : "Režiimi lüliti", diff --git a/apps/user_ldap/l10n/fr.js b/apps/user_ldap/l10n/fr.js index 9e863ada3b5..4a7b2631b79 100644 --- a/apps/user_ldap/l10n/fr.js +++ b/apps/user_ldap/l10n/fr.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Impossible de détecter le DN de base, veuillez le spécifier manuellement", "{nthServer}. Server" : "{nthServer}. Serveur", "No object found in the given Base DN. Please revise." : "Aucun objet trouvé dans le DN de base spécifié. Veuillez le vérifier.", - "More than 1.000 directory entries available." : "Il y a plus de 1000 entrées de répertoire disponibles.", " entries available within the provided Base DN" : "entrées disponibles dans le DN de base spécifié", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Une erreur est survenue. Veuillez vérifier le DN de base, ainsi que les paramètres de connexion et les informations d'identification", "Do you really want to delete the current Server Configuration?" : "Êtes-vous sûr de vouloir effacer la configuration serveur actuelle ?", diff --git a/apps/user_ldap/l10n/fr.json b/apps/user_ldap/l10n/fr.json index a26710c340b..344bbaf7282 100644 --- a/apps/user_ldap/l10n/fr.json +++ b/apps/user_ldap/l10n/fr.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Impossible de détecter le DN de base, veuillez le spécifier manuellement", "{nthServer}. Server" : "{nthServer}. Serveur", "No object found in the given Base DN. Please revise." : "Aucun objet trouvé dans le DN de base spécifié. Veuillez le vérifier.", - "More than 1.000 directory entries available." : "Il y a plus de 1000 entrées de répertoire disponibles.", " entries available within the provided Base DN" : "entrées disponibles dans le DN de base spécifié", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Une erreur est survenue. Veuillez vérifier le DN de base, ainsi que les paramètres de connexion et les informations d'identification", "Do you really want to delete the current Server Configuration?" : "Êtes-vous sûr de vouloir effacer la configuration serveur actuelle ?", diff --git a/apps/user_ldap/l10n/gl.js b/apps/user_ldap/l10n/gl.js index fac8aedc4aa..ea7aa9674fe 100644 --- a/apps/user_ldap/l10n/gl.js +++ b/apps/user_ldap/l10n/gl.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Non foi posíbel detectar o DN base, introdúzao manualmente.", "{nthServer}. Server" : "{nthServer}. Servidor", "No object found in the given Base DN. Please revise." : "Non se atopou o obxecto no DN base solicitado. Revíseo.", - "More than 1.000 directory entries available." : "Dispoñíbeis máis de 1.000 entradas de directorio.", " entries available within the provided Base DN" : "entradas dispoñíbeis no DN base fornecido", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Produciuse un erro. Comprobe o DN base, os axustes de conexión e as credenciais.", "Do you really want to delete the current Server Configuration?" : "Confirma que quere eliminar a configuración actual do servidor?", diff --git a/apps/user_ldap/l10n/gl.json b/apps/user_ldap/l10n/gl.json index b168f9d3058..53c96103238 100644 --- a/apps/user_ldap/l10n/gl.json +++ b/apps/user_ldap/l10n/gl.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Non foi posíbel detectar o DN base, introdúzao manualmente.", "{nthServer}. Server" : "{nthServer}. Servidor", "No object found in the given Base DN. Please revise." : "Non se atopou o obxecto no DN base solicitado. Revíseo.", - "More than 1.000 directory entries available." : "Dispoñíbeis máis de 1.000 entradas de directorio.", " entries available within the provided Base DN" : "entradas dispoñíbeis no DN base fornecido", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Produciuse un erro. Comprobe o DN base, os axustes de conexión e as credenciais.", "Do you really want to delete the current Server Configuration?" : "Confirma que quere eliminar a configuración actual do servidor?", diff --git a/apps/user_ldap/l10n/id.js b/apps/user_ldap/l10n/id.js index 402219f12bc..282b1a8181d 100644 --- a/apps/user_ldap/l10n/id.js +++ b/apps/user_ldap/l10n/id.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Tidak dapat mendeteksi Base DN, mohon masukkan secara manual.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Tidak ada obyek ditemukan di Base DN yang diberikan. Mohon diperiksa kembali.", - "More than 1.000 directory entries available." : "Lebih dari 1.000 entri direktori yang tersedia.", " entries available within the provided Base DN" : "entri tersedia didalam Base DN yang diberikan", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Terjadi kesalahan. Silakan periksa Base DN, serta pengaturan sambungan dan kredensial.", "Do you really want to delete the current Server Configuration?" : "Apakan Anda ingin menghapus Konfigurasi Server saat ini?", diff --git a/apps/user_ldap/l10n/id.json b/apps/user_ldap/l10n/id.json index bf8f0509fab..556c5fd6970 100644 --- a/apps/user_ldap/l10n/id.json +++ b/apps/user_ldap/l10n/id.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Tidak dapat mendeteksi Base DN, mohon masukkan secara manual.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Tidak ada obyek ditemukan di Base DN yang diberikan. Mohon diperiksa kembali.", - "More than 1.000 directory entries available." : "Lebih dari 1.000 entri direktori yang tersedia.", " entries available within the provided Base DN" : "entri tersedia didalam Base DN yang diberikan", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Terjadi kesalahan. Silakan periksa Base DN, serta pengaturan sambungan dan kredensial.", "Do you really want to delete the current Server Configuration?" : "Apakan Anda ingin menghapus Konfigurasi Server saat ini?", diff --git a/apps/user_ldap/l10n/it.js b/apps/user_ldap/l10n/it.js index 608bc3ebf27..88a5ceea447 100644 --- a/apps/user_ldap/l10n/it.js +++ b/apps/user_ldap/l10n/it.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Impossibile rilevare il DN base, digitalo manualmente.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Nessun oggetto trovato nel DN base specificato. Controlla.", - "More than 1.000 directory entries available." : "Più di 1.000 cartelle disponibili.", " entries available within the provided Base DN" : "voci disponibili all'interno del DN base", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Si è verificato un errore. Controlla il DN base, così come le impostazioni di connessione e le credenziali.", "Do you really want to delete the current Server Configuration?" : "Vuoi davvero eliminare la configurazione attuale del server?", diff --git a/apps/user_ldap/l10n/it.json b/apps/user_ldap/l10n/it.json index 93bc5522d37..cb8f6b11d73 100644 --- a/apps/user_ldap/l10n/it.json +++ b/apps/user_ldap/l10n/it.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Impossibile rilevare il DN base, digitalo manualmente.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Nessun oggetto trovato nel DN base specificato. Controlla.", - "More than 1.000 directory entries available." : "Più di 1.000 cartelle disponibili.", " entries available within the provided Base DN" : "voci disponibili all'interno del DN base", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Si è verificato un errore. Controlla il DN base, così come le impostazioni di connessione e le credenziali.", "Do you really want to delete the current Server Configuration?" : "Vuoi davvero eliminare la configurazione attuale del server?", diff --git a/apps/user_ldap/l10n/ja.js b/apps/user_ldap/l10n/ja.js index 2db99acf7af..3ba8bd8f2f3 100644 --- a/apps/user_ldap/l10n/ja.js +++ b/apps/user_ldap/l10n/ja.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "ベース DN を検出できませんでした。手動で入力してください。", "{nthServer}. Server" : "{nthServer}. サーバー", "No object found in the given Base DN. Please revise." : "指定されたベース DN でオブジェクトを見つけることができませんでした。修正をお願いします。", - "More than 1.000 directory entries available." : "1000 以上のディレクトリエントリが利用可能です。", " entries available within the provided Base DN" : "入力されたベースDNでエントリーが利用可能", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "エラーが発生しました。ベースDNをチェックし、接続設定と権限についても同様に確認してください。", "Do you really want to delete the current Server Configuration?" : "現在のサーバー設定を本当に削除してもよろしいですか?", diff --git a/apps/user_ldap/l10n/ja.json b/apps/user_ldap/l10n/ja.json index 3a9475699ae..64d40cd8e4a 100644 --- a/apps/user_ldap/l10n/ja.json +++ b/apps/user_ldap/l10n/ja.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "ベース DN を検出できませんでした。手動で入力してください。", "{nthServer}. Server" : "{nthServer}. サーバー", "No object found in the given Base DN. Please revise." : "指定されたベース DN でオブジェクトを見つけることができませんでした。修正をお願いします。", - "More than 1.000 directory entries available." : "1000 以上のディレクトリエントリが利用可能です。", " entries available within the provided Base DN" : "入力されたベースDNでエントリーが利用可能", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "エラーが発生しました。ベースDNをチェックし、接続設定と権限についても同様に確認してください。", "Do you really want to delete the current Server Configuration?" : "現在のサーバー設定を本当に削除してもよろしいですか?", diff --git a/apps/user_ldap/l10n/ko.js b/apps/user_ldap/l10n/ko.js index 6a14df58855..c08dd0e2a93 100644 --- a/apps/user_ldap/l10n/ko.js +++ b/apps/user_ldap/l10n/ko.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "기본 DN을 자동으로 감지할 수 없습니다. 직접 입력하십시오.", "{nthServer}. Server" : "{nthServer}. 서버", "No object found in the given Base DN. Please revise." : "입력한 기본 DN에서 객체를 찾을 수 없습니다. 다시 입력하십시오.", - "More than 1.000 directory entries available." : "디렉터리 항목이 1,000개 이상 존재합니다.", " entries available within the provided Base DN" : "개(지정한 DN의 기본 항목 수)", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "오류가 발생했습니다. 기본 DN, 연결 설정, 인증 정보를 확인하십시오.", "Do you really want to delete the current Server Configuration?" : "현재 서버 설정을 지우시겠습니까?", diff --git a/apps/user_ldap/l10n/ko.json b/apps/user_ldap/l10n/ko.json index 40fd85ca809..59037ab0a2b 100644 --- a/apps/user_ldap/l10n/ko.json +++ b/apps/user_ldap/l10n/ko.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "기본 DN을 자동으로 감지할 수 없습니다. 직접 입력하십시오.", "{nthServer}. Server" : "{nthServer}. 서버", "No object found in the given Base DN. Please revise." : "입력한 기본 DN에서 객체를 찾을 수 없습니다. 다시 입력하십시오.", - "More than 1.000 directory entries available." : "디렉터리 항목이 1,000개 이상 존재합니다.", " entries available within the provided Base DN" : "개(지정한 DN의 기본 항목 수)", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "오류가 발생했습니다. 기본 DN, 연결 설정, 인증 정보를 확인하십시오.", "Do you really want to delete the current Server Configuration?" : "현재 서버 설정을 지우시겠습니까?", diff --git a/apps/user_ldap/l10n/nb_NO.js b/apps/user_ldap/l10n/nb_NO.js index f92e3613193..8770dfa0841 100644 --- a/apps/user_ldap/l10n/nb_NO.js +++ b/apps/user_ldap/l10n/nb_NO.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Klarte ikke å påvise basis-DN. Det må skrives inn manuelt.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Intet objekt funnet i angitt basis-DN. Revider oppsettet.", - "More than 1.000 directory entries available." : "Mer enn 1000 katalogoppføringer tilgjengelig.", " entries available within the provided Base DN" : "oppføringer tilgjengelig innenfor angitt basis-DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Det oppstod en feil. Sjekk basis-DN, tilkoblingsoppsett og påloggingsdetaljer.", "Do you really want to delete the current Server Configuration?" : "Er du sikker på at du vil slette aktiv tjener-konfigurasjon?", diff --git a/apps/user_ldap/l10n/nb_NO.json b/apps/user_ldap/l10n/nb_NO.json index 268faa899c5..9cc0e4964dd 100644 --- a/apps/user_ldap/l10n/nb_NO.json +++ b/apps/user_ldap/l10n/nb_NO.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Klarte ikke å påvise basis-DN. Det må skrives inn manuelt.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Intet objekt funnet i angitt basis-DN. Revider oppsettet.", - "More than 1.000 directory entries available." : "Mer enn 1000 katalogoppføringer tilgjengelig.", " entries available within the provided Base DN" : "oppføringer tilgjengelig innenfor angitt basis-DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Det oppstod en feil. Sjekk basis-DN, tilkoblingsoppsett og påloggingsdetaljer.", "Do you really want to delete the current Server Configuration?" : "Er du sikker på at du vil slette aktiv tjener-konfigurasjon?", diff --git a/apps/user_ldap/l10n/nl.js b/apps/user_ldap/l10n/nl.js index 1606f1de128..f546cfd8150 100644 --- a/apps/user_ldap/l10n/nl.js +++ b/apps/user_ldap/l10n/nl.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Kon basis DN niet vaststellen, voer de gegevens handmatig in.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Geen object gevonden in de basis DN. Review instellingen.", - "More than 1.000 directory entries available." : "Meer dan 1000 directory namen beschikbaar.", " entries available within the provided Base DN" : "accounts beschikbaar binnen de provider Basis DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Er trad een fout op. Controleer de Basis DN en de verbindingsinstellingen en inloggegevens.", "Do you really want to delete the current Server Configuration?" : "Wilt u werkelijk de huidige Serverconfiguratie verwijderen?", diff --git a/apps/user_ldap/l10n/nl.json b/apps/user_ldap/l10n/nl.json index 4b930d7b4c9..fc58e43347d 100644 --- a/apps/user_ldap/l10n/nl.json +++ b/apps/user_ldap/l10n/nl.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Kon basis DN niet vaststellen, voer de gegevens handmatig in.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Geen object gevonden in de basis DN. Review instellingen.", - "More than 1.000 directory entries available." : "Meer dan 1000 directory namen beschikbaar.", " entries available within the provided Base DN" : "accounts beschikbaar binnen de provider Basis DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Er trad een fout op. Controleer de Basis DN en de verbindingsinstellingen en inloggegevens.", "Do you really want to delete the current Server Configuration?" : "Wilt u werkelijk de huidige Serverconfiguratie verwijderen?", diff --git a/apps/user_ldap/l10n/oc.js b/apps/user_ldap/l10n/oc.js index 16a136649d7..97ad04c7ec4 100644 --- a/apps/user_ldap/l10n/oc.js +++ b/apps/user_ldap/l10n/oc.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Impossible de detectar lo DN de basa, especificatz-lo manualament", "{nthServer}. Server" : "{nthServer}. Servidor", "No object found in the given Base DN. Please revise." : "Cap d'objècte pas trobat dins lo DN de basa especificat. Verificatz-lo.", - "More than 1.000 directory entries available." : "I a mai de 1000 entradas de repertòri disponiblas.", " entries available within the provided Base DN" : "entradas disponiblas dins lo DN de basa especificat", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Una error s'es produsida. Verificatz lo DN de basa, e tanben los paramètres de connexion e las informacions d'identificacion.", "Do you really want to delete the current Server Configuration?" : "Sètz segur que volètz escafar la configuracion servidor actuala ?", diff --git a/apps/user_ldap/l10n/oc.json b/apps/user_ldap/l10n/oc.json index c7489f3f2b4..8db8ef6297f 100644 --- a/apps/user_ldap/l10n/oc.json +++ b/apps/user_ldap/l10n/oc.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Impossible de detectar lo DN de basa, especificatz-lo manualament", "{nthServer}. Server" : "{nthServer}. Servidor", "No object found in the given Base DN. Please revise." : "Cap d'objècte pas trobat dins lo DN de basa especificat. Verificatz-lo.", - "More than 1.000 directory entries available." : "I a mai de 1000 entradas de repertòri disponiblas.", " entries available within the provided Base DN" : "entradas disponiblas dins lo DN de basa especificat", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Una error s'es produsida. Verificatz lo DN de basa, e tanben los paramètres de connexion e las informacions d'identificacion.", "Do you really want to delete the current Server Configuration?" : "Sètz segur que volètz escafar la configuracion servidor actuala ?", diff --git a/apps/user_ldap/l10n/pt_BR.js b/apps/user_ldap/l10n/pt_BR.js index f2ad0ca8a3a..3254610be2a 100644 --- a/apps/user_ldap/l10n/pt_BR.js +++ b/apps/user_ldap/l10n/pt_BR.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Não foi possível detectar a Base DN, por favor entre manualmente.", "{nthServer}. Server" : "Servidor {nthServer}.", "No object found in the given Base DN. Please revise." : "Nenhum objeto encontrado ba Base DN informada. Por favor revise.", - "More than 1.000 directory entries available." : "Mais de 1.000 entradas de diretórios disponíveis.", " entries available within the provided Base DN" : "entradas disponíveis na Base DN disponibilizada", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Um erro ocorreu. Por favor verifique a Base DN, e também a conexção e credenciais.", "Do you really want to delete the current Server Configuration?" : "Você quer realmente deletar as atuais Configurações de Servidor?", diff --git a/apps/user_ldap/l10n/pt_BR.json b/apps/user_ldap/l10n/pt_BR.json index 752fd653884..de03f9778d0 100644 --- a/apps/user_ldap/l10n/pt_BR.json +++ b/apps/user_ldap/l10n/pt_BR.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Não foi possível detectar a Base DN, por favor entre manualmente.", "{nthServer}. Server" : "Servidor {nthServer}.", "No object found in the given Base DN. Please revise." : "Nenhum objeto encontrado ba Base DN informada. Por favor revise.", - "More than 1.000 directory entries available." : "Mais de 1.000 entradas de diretórios disponíveis.", " entries available within the provided Base DN" : "entradas disponíveis na Base DN disponibilizada", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Um erro ocorreu. Por favor verifique a Base DN, e também a conexção e credenciais.", "Do you really want to delete the current Server Configuration?" : "Você quer realmente deletar as atuais Configurações de Servidor?", diff --git a/apps/user_ldap/l10n/pt_PT.js b/apps/user_ldap/l10n/pt_PT.js index 7288c683303..3863326e6c3 100644 --- a/apps/user_ldap/l10n/pt_PT.js +++ b/apps/user_ldap/l10n/pt_PT.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Não foi possível detetar o ND de base, por favor introduza-o manualmente.", "{nthServer}. Server" : "{nthServer}. Servidor", "No object found in the given Base DN. Please revise." : "Nenhum objecto encontrado na Base DN fornecida. Por favor verifique.", - "More than 1.000 directory entries available." : "Mais de 1,000 entradas de diretório disponíveis.", " entries available within the provided Base DN" : "entradas disponíveis no ND de base fornecido", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ocorreu um erro. Por favor verifique o ND de base, bem como as definições de ligação e as credenciais.", "Do you really want to delete the current Server Configuration?" : "Deseja realmente apagar as configurações de servidor actuais?", diff --git a/apps/user_ldap/l10n/pt_PT.json b/apps/user_ldap/l10n/pt_PT.json index 5de030281b3..729674e0b2c 100644 --- a/apps/user_ldap/l10n/pt_PT.json +++ b/apps/user_ldap/l10n/pt_PT.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Não foi possível detetar o ND de base, por favor introduza-o manualmente.", "{nthServer}. Server" : "{nthServer}. Servidor", "No object found in the given Base DN. Please revise." : "Nenhum objecto encontrado na Base DN fornecida. Por favor verifique.", - "More than 1.000 directory entries available." : "Mais de 1,000 entradas de diretório disponíveis.", " entries available within the provided Base DN" : "entradas disponíveis no ND de base fornecido", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ocorreu um erro. Por favor verifique o ND de base, bem como as definições de ligação e as credenciais.", "Do you really want to delete the current Server Configuration?" : "Deseja realmente apagar as configurações de servidor actuais?", diff --git a/apps/user_ldap/l10n/ru.js b/apps/user_ldap/l10n/ru.js index 81078d595f0..40705449edf 100644 --- a/apps/user_ldap/l10n/ru.js +++ b/apps/user_ldap/l10n/ru.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Не возможно обнаружить Base DN, пожалуйста задайте в ручную.", "{nthServer}. Server" : "Сервер {nthServer}.", "No object found in the given Base DN. Please revise." : "Не найдено объектов в Base DN. Пожалуйста перепроверьте.", - "More than 1.000 directory entries available." : "В каталоге доступно более 1.000 записей.", " entries available within the provided Base DN" : "элементы доступные в Базе", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Произошла ошибка. Пожалуйста проверьте базу поиска DN, а также настройки подключения и учетные данные.", "Do you really want to delete the current Server Configuration?" : "Вы действительно хотите удалить существующую конфигурацию сервера?", diff --git a/apps/user_ldap/l10n/ru.json b/apps/user_ldap/l10n/ru.json index 834a9b7c05f..4a6f9ea52d0 100644 --- a/apps/user_ldap/l10n/ru.json +++ b/apps/user_ldap/l10n/ru.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Не возможно обнаружить Base DN, пожалуйста задайте в ручную.", "{nthServer}. Server" : "Сервер {nthServer}.", "No object found in the given Base DN. Please revise." : "Не найдено объектов в Base DN. Пожалуйста перепроверьте.", - "More than 1.000 directory entries available." : "В каталоге доступно более 1.000 записей.", " entries available within the provided Base DN" : "элементы доступные в Базе", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Произошла ошибка. Пожалуйста проверьте базу поиска DN, а также настройки подключения и учетные данные.", "Do you really want to delete the current Server Configuration?" : "Вы действительно хотите удалить существующую конфигурацию сервера?", diff --git a/apps/user_ldap/l10n/sk_SK.js b/apps/user_ldap/l10n/sk_SK.js index 4a41059ff3e..6eca3c2735b 100644 --- a/apps/user_ldap/l10n/sk_SK.js +++ b/apps/user_ldap/l10n/sk_SK.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Nemožno automaticky detekovať základnú DN, zadajte ručne prosím.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Objekt nebol nájdený v zadanej základnej DN. Overte to prosím.", - "More than 1.000 directory entries available." : "K dispozícii je viac ako 1.000 priečinkov.", " entries available within the provided Base DN" : "dostupných záznamov v zadanej základnej DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Nastala chyba. Overte základnú DN, nastavenia pripojenia a prihlasovacie údaje.", "Do you really want to delete the current Server Configuration?" : "Naozaj chcete zmazať súčasné nastavenie servera?", diff --git a/apps/user_ldap/l10n/sk_SK.json b/apps/user_ldap/l10n/sk_SK.json index 126c86c8c3b..ca7275af8e6 100644 --- a/apps/user_ldap/l10n/sk_SK.json +++ b/apps/user_ldap/l10n/sk_SK.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Nemožno automaticky detekovať základnú DN, zadajte ručne prosím.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Objekt nebol nájdený v zadanej základnej DN. Overte to prosím.", - "More than 1.000 directory entries available." : "K dispozícii je viac ako 1.000 priečinkov.", " entries available within the provided Base DN" : "dostupných záznamov v zadanej základnej DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Nastala chyba. Overte základnú DN, nastavenia pripojenia a prihlasovacie údaje.", "Do you really want to delete the current Server Configuration?" : "Naozaj chcete zmazať súčasné nastavenie servera?", diff --git a/apps/user_ldap/l10n/sl.js b/apps/user_ldap/l10n/sl.js index 86a372efd9f..d3712c273f0 100644 --- a/apps/user_ldap/l10n/sl.js +++ b/apps/user_ldap/l10n/sl.js @@ -17,7 +17,6 @@ OC.L10N.register( "Select groups" : "Izberi skupine", "Select object classes" : "Izbor razredov predmeta", "{nthServer}. Server" : "{nthServer}. strežnik", - "More than 1.000 directory entries available." : "Na voljo je več kot 1.000 elementov imenika.", "Do you really want to delete the current Server Configuration?" : "Ali res želite izbrisati trenutne nastavitve strežnika?", "Confirm Deletion" : "Potrdi brisanje", "Mode switch" : "Preklop načina", diff --git a/apps/user_ldap/l10n/sl.json b/apps/user_ldap/l10n/sl.json index 268d5f09c91..14e73e628a0 100644 --- a/apps/user_ldap/l10n/sl.json +++ b/apps/user_ldap/l10n/sl.json @@ -15,7 +15,6 @@ "Select groups" : "Izberi skupine", "Select object classes" : "Izbor razredov predmeta", "{nthServer}. Server" : "{nthServer}. strežnik", - "More than 1.000 directory entries available." : "Na voljo je več kot 1.000 elementov imenika.", "Do you really want to delete the current Server Configuration?" : "Ali res želite izbrisati trenutne nastavitve strežnika?", "Confirm Deletion" : "Potrdi brisanje", "Mode switch" : "Preklop načina", diff --git a/apps/user_ldap/l10n/sq.js b/apps/user_ldap/l10n/sq.js index 0c46ff72a98..4ec40ef5957 100644 --- a/apps/user_ldap/l10n/sq.js +++ b/apps/user_ldap/l10n/sq.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "S’u zbulua dot DN Bazë, ju lutemi, jepeni dorazi.", "{nthServer}. Server" : "{nthServer}. Shërbyes", "No object found in the given Base DN. Please revise." : "Në DN Bazë të dhën s’u gjet objekt. Ju lutemi, rishikojeni.", - "More than 1.000 directory entries available." : "Më tepër se 1.000 zëra drejtorie gati.", " entries available within the provided Base DN" : " zëra të gatshëm brenda DN-së Bazë të dhënë", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ndodhi një gabim. Ju lutemi, kontrolloni DN-në Bazë, sie dhe rregullimet për lidhjen dhe kredencialet.", "Do you really want to delete the current Server Configuration?" : "Doni vërtet të fshihet Formësimi i tanishëm i Shërbyesit?", diff --git a/apps/user_ldap/l10n/sq.json b/apps/user_ldap/l10n/sq.json index 246adb316c2..2e50290f18c 100644 --- a/apps/user_ldap/l10n/sq.json +++ b/apps/user_ldap/l10n/sq.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "S’u zbulua dot DN Bazë, ju lutemi, jepeni dorazi.", "{nthServer}. Server" : "{nthServer}. Shërbyes", "No object found in the given Base DN. Please revise." : "Në DN Bazë të dhën s’u gjet objekt. Ju lutemi, rishikojeni.", - "More than 1.000 directory entries available." : "Më tepër se 1.000 zëra drejtorie gati.", " entries available within the provided Base DN" : " zëra të gatshëm brenda DN-së Bazë të dhënë", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ndodhi një gabim. Ju lutemi, kontrolloni DN-në Bazë, sie dhe rregullimet për lidhjen dhe kredencialet.", "Do you really want to delete the current Server Configuration?" : "Doni vërtet të fshihet Formësimi i tanishëm i Shërbyesit?", diff --git a/apps/user_ldap/l10n/sr.js b/apps/user_ldap/l10n/sr.js index e95d656d680..1ccfefcb7a8 100644 --- a/apps/user_ldap/l10n/sr.js +++ b/apps/user_ldap/l10n/sr.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Не могу да откријем базни ДН. Унесите га ручно.", "{nthServer}. Server" : "{nthServer}. Сервер", "No object found in the given Base DN. Please revise." : "Нема објекта за дати базни ДН. Проверите.", - "More than 1.000 directory entries available." : "Више од 1000 уноса је доступно.", " entries available within the provided Base DN" : "уноса доступно за дати базни ДН", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Грешка. Проверите базни ДН као и поставке везе и акредитиве.", "Do you really want to delete the current Server Configuration?" : "Да ли стварно желите да обришете тренутну конфигурацију сервера?", diff --git a/apps/user_ldap/l10n/sr.json b/apps/user_ldap/l10n/sr.json index a52d7184b3a..658edafc77b 100644 --- a/apps/user_ldap/l10n/sr.json +++ b/apps/user_ldap/l10n/sr.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Не могу да откријем базни ДН. Унесите га ручно.", "{nthServer}. Server" : "{nthServer}. Сервер", "No object found in the given Base DN. Please revise." : "Нема објекта за дати базни ДН. Проверите.", - "More than 1.000 directory entries available." : "Више од 1000 уноса је доступно.", " entries available within the provided Base DN" : "уноса доступно за дати базни ДН", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Грешка. Проверите базни ДН као и поставке везе и акредитиве.", "Do you really want to delete the current Server Configuration?" : "Да ли стварно желите да обришете тренутну конфигурацију сервера?", diff --git a/apps/user_ldap/l10n/th_TH.js b/apps/user_ldap/l10n/th_TH.js index d088d01f6c6..c848d137464 100644 --- a/apps/user_ldap/l10n/th_TH.js +++ b/apps/user_ldap/l10n/th_TH.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "ไม่สามารถตรวจสอบ Base DN โปรดเลือกด้วยตนเอง", "{nthServer}. Server" : "เซิร์ฟเวอร์ {nthServer}", "No object found in the given Base DN. Please revise." : "ไม่พบวัตถุที่กำหนดใน Base DN กรุณาแก้ไข", - "More than 1.000 directory entries available." : "มีรายการไดเรกทอรีมากกว่า 1,000 รายการ", " entries available within the provided Base DN" : "รายการที่มีอยู่ใน Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "เกิดข้อผิดพลาด กรุณาตรวจสอบ Base DN เช่นเดียวกับการตั้งค่าการเชื่อมต่อและข้อมูลที่สำคัญ", "Do you really want to delete the current Server Configuration?" : "คุณแน่ใจแล้วหรือว่าต้องการลบการกำหนดค่าเซิร์ฟเวอร์ปัจจุบันทิ้งไป?", diff --git a/apps/user_ldap/l10n/th_TH.json b/apps/user_ldap/l10n/th_TH.json index 87afedbeeb5..6afa6f2bbc4 100644 --- a/apps/user_ldap/l10n/th_TH.json +++ b/apps/user_ldap/l10n/th_TH.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "ไม่สามารถตรวจสอบ Base DN โปรดเลือกด้วยตนเอง", "{nthServer}. Server" : "เซิร์ฟเวอร์ {nthServer}", "No object found in the given Base DN. Please revise." : "ไม่พบวัตถุที่กำหนดใน Base DN กรุณาแก้ไข", - "More than 1.000 directory entries available." : "มีรายการไดเรกทอรีมากกว่า 1,000 รายการ", " entries available within the provided Base DN" : "รายการที่มีอยู่ใน Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "เกิดข้อผิดพลาด กรุณาตรวจสอบ Base DN เช่นเดียวกับการตั้งค่าการเชื่อมต่อและข้อมูลที่สำคัญ", "Do you really want to delete the current Server Configuration?" : "คุณแน่ใจแล้วหรือว่าต้องการลบการกำหนดค่าเซิร์ฟเวอร์ปัจจุบันทิ้งไป?", diff --git a/apps/user_ldap/l10n/tr.js b/apps/user_ldap/l10n/tr.js index 944d39928d0..cbe95a194c5 100644 --- a/apps/user_ldap/l10n/tr.js +++ b/apps/user_ldap/l10n/tr.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Base DN tespit edilemedi, lütfen elle girin.", "{nthServer}. Server" : "{nthServer}. Sunucu", "No object found in the given Base DN. Please revise." : "Girilen Base DN içerisinde nesne bulunamadı. Lütfen gözden geçirin.", - "More than 1.000 directory entries available." : "1.000'den fazla dizin girdisi mevcut.", " entries available within the provided Base DN" : " girdi sağlanan Base DN içerisinde mevcut", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Bir hata oluştu. Lütfen Base DN ile birlikte bağlantı ayarlarını ve kimlik bilgilerini denetleyin.", "Do you really want to delete the current Server Configuration?" : "Şu anki sunucu yapılandırmasını silmek istediğinizden emin misiniz?", diff --git a/apps/user_ldap/l10n/tr.json b/apps/user_ldap/l10n/tr.json index 553dfe6cdbd..2bd0bd59907 100644 --- a/apps/user_ldap/l10n/tr.json +++ b/apps/user_ldap/l10n/tr.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "Base DN tespit edilemedi, lütfen elle girin.", "{nthServer}. Server" : "{nthServer}. Sunucu", "No object found in the given Base DN. Please revise." : "Girilen Base DN içerisinde nesne bulunamadı. Lütfen gözden geçirin.", - "More than 1.000 directory entries available." : "1.000'den fazla dizin girdisi mevcut.", " entries available within the provided Base DN" : " girdi sağlanan Base DN içerisinde mevcut", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Bir hata oluştu. Lütfen Base DN ile birlikte bağlantı ayarlarını ve kimlik bilgilerini denetleyin.", "Do you really want to delete the current Server Configuration?" : "Şu anki sunucu yapılandırmasını silmek istediğinizden emin misiniz?", diff --git a/apps/user_ldap/l10n/zh_TW.js b/apps/user_ldap/l10n/zh_TW.js index c6830f96a83..244206927ba 100644 --- a/apps/user_ldap/l10n/zh_TW.js +++ b/apps/user_ldap/l10n/zh_TW.js @@ -24,7 +24,6 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "無法偵測到Base DN,請手動輸入", "{nthServer}. Server" : "{nthServer}. 伺服器", "No object found in the given Base DN. Please revise." : "在Base DN中找不到物件,請重新修改", - "More than 1.000 directory entries available." : "目前有超過 1.000 個資料夾項目是可以使用的", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "產生錯誤,請檢查Base DN,以及連線設定和驗證", "Do you really want to delete the current Server Configuration?" : "您真的要刪除現在的伺服器設定嗎?", "Confirm Deletion" : "確認刪除", diff --git a/apps/user_ldap/l10n/zh_TW.json b/apps/user_ldap/l10n/zh_TW.json index 0661836bac2..35b5b5bad27 100644 --- a/apps/user_ldap/l10n/zh_TW.json +++ b/apps/user_ldap/l10n/zh_TW.json @@ -22,7 +22,6 @@ "Could not detect Base DN, please enter it manually." : "無法偵測到Base DN,請手動輸入", "{nthServer}. Server" : "{nthServer}. 伺服器", "No object found in the given Base DN. Please revise." : "在Base DN中找不到物件,請重新修改", - "More than 1.000 directory entries available." : "目前有超過 1.000 個資料夾項目是可以使用的", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "產生錯誤,請檢查Base DN,以及連線設定和驗證", "Do you really want to delete the current Server Configuration?" : "您真的要刪除現在的伺服器設定嗎?", "Confirm Deletion" : "確認刪除", diff --git a/core/l10n/af_ZA.js b/core/l10n/af_ZA.js index 3bb344ed878..151311b4848 100644 --- a/core/l10n/af_ZA.js +++ b/core/l10n/af_ZA.js @@ -107,9 +107,9 @@ OC.L10N.register( "Database tablespace" : "Databasis tabelspasie", "Database host" : "Databasis gasheer", "Finish setup" : "Maak opstelling klaar", + "Hey there,

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

" : "Halo daar,

wou jou net laat weet dat %s %s met jou gedeel het.
Sien alles!

", "Log out" : "Teken uit", "Log in" : "Teken aan", - "Alternative Logins" : "Alternatiewe aantekeninge", - "Hey there,

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

" : "Halo daar,

wou jou net laat weet dat %s %s met jou gedeel het.
Sien alles!

" + "Alternative Logins" : "Alternatiewe aantekeninge" }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/af_ZA.json b/core/l10n/af_ZA.json index 0b0e5a8e416..7d30b3c6566 100644 --- a/core/l10n/af_ZA.json +++ b/core/l10n/af_ZA.json @@ -105,9 +105,9 @@ "Database tablespace" : "Databasis tabelspasie", "Database host" : "Databasis gasheer", "Finish setup" : "Maak opstelling klaar", + "Hey there,

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

" : "Halo daar,

wou jou net laat weet dat %s %s met jou gedeel het.
Sien alles!

", "Log out" : "Teken uit", "Log in" : "Teken aan", - "Alternative Logins" : "Alternatiewe aantekeninge", - "Hey there,

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

" : "Halo daar,

wou jou net laat weet dat %s %s met jou gedeel het.
Sien alles!

" + "Alternative Logins" : "Alternatiewe aantekeninge" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/core/l10n/ast.js b/core/l10n/ast.js index 603e684d7e2..e0775c75569 100644 --- a/core/l10n/ast.js +++ b/core/l10n/ast.js @@ -183,7 +183,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Contauta col alministrador si esti problema sigui apaeciendo.", "Thank you for your patience." : "Gracies pola to paciencia.", "You are accessing the server from an untrusted domain." : "Tas accediendo al sirvidor dende un dominiu non confiáu.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor, contauta col alministrador. Si yes l'alministrador, configura l'axuste \"trusted_domain\" en config/config.php. Hai un exemplu en config/config.sample.php.", "Add \"%s\" as trusted domain" : "Amestáu \"%s\" como dominiu de confianza", "The theme %s has been disabled." : "Deshabilitóse'l tema %s.", "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Enantes de siguir, asegúrate de que se fizo una copia de seguridá de la base de datos, la carpeta de configuración y la carpeta de datos.", diff --git a/core/l10n/ast.json b/core/l10n/ast.json index 02df7fc7b18..a4324339829 100644 --- a/core/l10n/ast.json +++ b/core/l10n/ast.json @@ -181,7 +181,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Contauta col alministrador si esti problema sigui apaeciendo.", "Thank you for your patience." : "Gracies pola to paciencia.", "You are accessing the server from an untrusted domain." : "Tas accediendo al sirvidor dende un dominiu non confiáu.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor, contauta col alministrador. Si yes l'alministrador, configura l'axuste \"trusted_domain\" en config/config.php. Hai un exemplu en config/config.sample.php.", "Add \"%s\" as trusted domain" : "Amestáu \"%s\" como dominiu de confianza", "The theme %s has been disabled." : "Deshabilitóse'l tema %s.", "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Enantes de siguir, asegúrate de que se fizo una copia de seguridá de la base de datos, la carpeta de configuración y la carpeta de datos.", diff --git a/core/l10n/az.js b/core/l10n/az.js index 10532ce6607..234431ec3b9 100644 --- a/core/l10n/az.js +++ b/core/l10n/az.js @@ -85,7 +85,6 @@ OC.L10N.register( "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Xüsusilə fayl sinxronizasiyası üçün desktop client-dən istifadə edilərsə, SQLite məsləhət görülmür.", "Search" : "Axtarış", "Log in" : "Giriş", - "You are accessing the server from an untrusted domain." : "Siz serverə inamsız domain-dən girməyə çalışırsız.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Xahiş olunur inzibatçı ilə əlaqə saxlayasınız. Eger siz bu xidmətin inzibatçısısınizsa, \"trusted_domain\" configini config/config.php faylinda düzgün qeyd edin. Config nüsxəsi config/config.sample.php faylında qeyd edilmişdir." + "You are accessing the server from an untrusted domain." : "Siz serverə inamsız domain-dən girməyə çalışırsız." }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/az.json b/core/l10n/az.json index ebfeca74bf7..4d45bdd9d96 100644 --- a/core/l10n/az.json +++ b/core/l10n/az.json @@ -83,7 +83,6 @@ "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Xüsusilə fayl sinxronizasiyası üçün desktop client-dən istifadə edilərsə, SQLite məsləhət görülmür.", "Search" : "Axtarış", "Log in" : "Giriş", - "You are accessing the server from an untrusted domain." : "Siz serverə inamsız domain-dən girməyə çalışırsız.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Xahiş olunur inzibatçı ilə əlaqə saxlayasınız. Eger siz bu xidmətin inzibatçısısınizsa, \"trusted_domain\" configini config/config.php faylinda düzgün qeyd edin. Config nüsxəsi config/config.sample.php faylında qeyd edilmişdir." + "You are accessing the server from an untrusted domain." : "Siz serverə inamsız domain-dən girməyə çalışırsız." },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/core/l10n/bg_BG.js b/core/l10n/bg_BG.js index ba6a1fa0b7c..34df1311847 100644 --- a/core/l10n/bg_BG.js +++ b/core/l10n/bg_BG.js @@ -202,6 +202,7 @@ OC.L10N.register( "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Особено, когато използвате клиент за работен плот за синхронизация, използването на SQLite e непрепоръчително.", "Finish setup" : "Завършване на настройките", "Finishing …" : "Завършване...", + "Hey there,

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

" : "Здрасти,

само да те уведомя, че %s сподели %s с теб.\n
Разгледай го!

.", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Това приложение изисква JavaScript, за да функционира правилно. Моля, {linkstart}включи JavaScript{linkend} и презареди страницата.", "Log out" : "Отписване", "Search" : "Търсене", @@ -209,13 +210,11 @@ OC.L10N.register( "Please contact your administrator." : "Моля, свържете се с администратора.", "Log in" : "Вписване", "Alternative Logins" : "Алтернативни методи на вписване", - "Hey there,

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

" : "Здрасти,

само да те уведомя, че %s сподели %s с теб.\n
Разгледай го!

.", "This ownCloud instance is currently in single user mode." : "В момента този ownCloud е в режим допускащ само един потребител.", "This means only administrators can use the instance." : "Това означава, че само администраторът може да го използва.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Свържи се със системния си администратор ако това съобщение се задържи твърде дълго или се е появило неочаквано.", "Thank you for your patience." : "Благодарим за търпението.", "You are accessing the server from an untrusted domain." : "Свръзваш се със сървъра от неодобрен домейн.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Моля, свържи се с администратора. Ако ти си администраторът, на този сървър, промени \"trusted_domain\" настройките в config/config.php. Примерна конфигурация е приложена в config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимост от конфигурацията ти, като администратор може натискайки бутонът по-долу да отбележиш домейнът като сигурен.", "Add \"%s\" as trusted domain" : "Добави \"%s\" като сигурен домейн", "The theme %s has been disabled." : "Темата %s бе изключена.", diff --git a/core/l10n/bg_BG.json b/core/l10n/bg_BG.json index fcd0a8de749..bcce1747bbd 100644 --- a/core/l10n/bg_BG.json +++ b/core/l10n/bg_BG.json @@ -200,6 +200,7 @@ "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Особено, когато използвате клиент за работен плот за синхронизация, използването на SQLite e непрепоръчително.", "Finish setup" : "Завършване на настройките", "Finishing …" : "Завършване...", + "Hey there,

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

" : "Здрасти,

само да те уведомя, че %s сподели %s с теб.\n
Разгледай го!

.", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Това приложение изисква JavaScript, за да функционира правилно. Моля, {linkstart}включи JavaScript{linkend} и презареди страницата.", "Log out" : "Отписване", "Search" : "Търсене", @@ -207,13 +208,11 @@ "Please contact your administrator." : "Моля, свържете се с администратора.", "Log in" : "Вписване", "Alternative Logins" : "Алтернативни методи на вписване", - "Hey there,

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

" : "Здрасти,

само да те уведомя, че %s сподели %s с теб.\n
Разгледай го!

.", "This ownCloud instance is currently in single user mode." : "В момента този ownCloud е в режим допускащ само един потребител.", "This means only administrators can use the instance." : "Това означава, че само администраторът може да го използва.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Свържи се със системния си администратор ако това съобщение се задържи твърде дълго или се е появило неочаквано.", "Thank you for your patience." : "Благодарим за търпението.", "You are accessing the server from an untrusted domain." : "Свръзваш се със сървъра от неодобрен домейн.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Моля, свържи се с администратора. Ако ти си администраторът, на този сървър, промени \"trusted_domain\" настройките в config/config.php. Примерна конфигурация е приложена в config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимост от конфигурацията ти, като администратор може натискайки бутонът по-долу да отбележиш домейнът като сигурен.", "Add \"%s\" as trusted domain" : "Добави \"%s\" като сигурен домейн", "The theme %s has been disabled." : "Темата %s бе изключена.", diff --git a/core/l10n/bs.js b/core/l10n/bs.js index ebda3c75beb..7d0664e38ee 100644 --- a/core/l10n/bs.js +++ b/core/l10n/bs.js @@ -182,19 +182,18 @@ OC.L10N.register( "Database host" : "Glavno računalo (host) baze podataka", "Finish setup" : "Završite postavke", "Finishing …" : "Završavanje...", + "Hey there,

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

" : "Hej,

upravo vam javljam da je %s s vama podijelio %s.
Pogledajte!

", "Log out" : "Odjava", "Search" : "Potraži", "Server side authentication failed!" : "Autentikacija na strani servera nije uspjela!", "Please contact your administrator." : "Molim kontaktirajte svog administratora.", "Log in" : "Prijava", "Alternative Logins" : "Alternativne Prijave", - "Hey there,

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

" : "Hej,

upravo vam javljam da je %s s vama podijelio %s.
Pogledajte!

", "This ownCloud instance is currently in single user mode." : "Ova ownCloud instanca je trenutno u jednokorisničkom načinu rada.", "This means only administrators can use the instance." : "To znači da tu instancu mogu koristiti samo administratori.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte svog administratora sistema ako se ova poruka ponavlja ili se pojavila neočekivano.", "Thank you for your patience." : "Hvala vam na strpljenju", "You are accessing the server from an untrusted domain." : "Pristupate serveru sa nepouzdane domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molim kontaktirajte vašeg administratora. Ako ste vi administrator ove instance, konfigurišite postavku \"trusted_domain\" u config/config.php. Primjer konfiguracije ponuđen je u config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ovisno o vašoj konfiguraciji, kao administrator vi biste također mogli koristiti dugme ispod za povjeru toj domeni.", "Add \"%s\" as trusted domain" : "Dodajte \"%s\" kao povjerenu/pouzdanu domenu.", "The theme %s has been disabled." : "Tema %s je onemogućena", diff --git a/core/l10n/bs.json b/core/l10n/bs.json index 80d9ac77199..e221dba005d 100644 --- a/core/l10n/bs.json +++ b/core/l10n/bs.json @@ -180,19 +180,18 @@ "Database host" : "Glavno računalo (host) baze podataka", "Finish setup" : "Završite postavke", "Finishing …" : "Završavanje...", + "Hey there,

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

" : "Hej,

upravo vam javljam da je %s s vama podijelio %s.
Pogledajte!

", "Log out" : "Odjava", "Search" : "Potraži", "Server side authentication failed!" : "Autentikacija na strani servera nije uspjela!", "Please contact your administrator." : "Molim kontaktirajte svog administratora.", "Log in" : "Prijava", "Alternative Logins" : "Alternativne Prijave", - "Hey there,

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

" : "Hej,

upravo vam javljam da je %s s vama podijelio %s.
Pogledajte!

", "This ownCloud instance is currently in single user mode." : "Ova ownCloud instanca je trenutno u jednokorisničkom načinu rada.", "This means only administrators can use the instance." : "To znači da tu instancu mogu koristiti samo administratori.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte svog administratora sistema ako se ova poruka ponavlja ili se pojavila neočekivano.", "Thank you for your patience." : "Hvala vam na strpljenju", "You are accessing the server from an untrusted domain." : "Pristupate serveru sa nepouzdane domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molim kontaktirajte vašeg administratora. Ako ste vi administrator ove instance, konfigurišite postavku \"trusted_domain\" u config/config.php. Primjer konfiguracije ponuđen je u config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ovisno o vašoj konfiguraciji, kao administrator vi biste također mogli koristiti dugme ispod za povjeru toj domeni.", "Add \"%s\" as trusted domain" : "Dodajte \"%s\" kao povjerenu/pouzdanu domenu.", "The theme %s has been disabled." : "Tema %s je onemogućena", diff --git a/core/l10n/ca.js b/core/l10n/ca.js index ee60372c21c..f1eb5f51db9 100644 --- a/core/l10n/ca.js +++ b/core/l10n/ca.js @@ -233,6 +233,7 @@ OC.L10N.register( "Finishing …" : "Acabant...", "Need help?" : "Necessites ajuda?", "See the documentation" : "Consulti la documentació", + "Hey there,

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

" : "Ei,

només fer-vos saber que %s us ha comparti %s.
Mireu-ho!", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Aquesta aplicació requereix Javascript per al seu correcte funcionament . Per favor, {linkstart}habiliti Javascript{linkend} i torni a carregar la pàgina.", "Log out" : "Surt", "Search" : "Cerca", @@ -243,13 +244,11 @@ OC.L10N.register( "Log in" : "Inici de sessió", "Wrong password. Reset it?" : "Contrasenya incorrecta. Voleu restablir-la?", "Alternative Logins" : "Acreditacions alternatives", - "Hey there,

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

" : "Ei,

només fer-vos saber que %s us ha comparti %s.
Mireu-ho!", "This ownCloud instance is currently in single user mode." : "La instància ownCloud està en mode d'usuari únic.", "This means only administrators can use the instance." : "Això significa que només els administradors poden usar la instància.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacteu amb l'administrador del sistema si aquest missatge persisteix o apareix inesperadament.", "Thank you for your patience." : "Gràcies per la paciència.", "You are accessing the server from an untrusted domain." : "Esteu accedint al servidor des d'un domini no fiable", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contacteu amb l'administrador. Si sou un administrador d'aquesta instància, configureu el paràmetre \"trusted_domain\" a config/config.php. Hi ha un exemple de configuració a config/config.sampe.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En funció de la teva configuració, com a administrador podries utilitzar el botó d'abaix per confiar en aquest domini.", "Add \"%s\" as trusted domain" : "Afegeix \"%s\" com a domini de confiança", "App update required" : "Cal que actualitzeu la aplicació", diff --git a/core/l10n/ca.json b/core/l10n/ca.json index bca55a0fe0c..0b14ef2ff2a 100644 --- a/core/l10n/ca.json +++ b/core/l10n/ca.json @@ -231,6 +231,7 @@ "Finishing …" : "Acabant...", "Need help?" : "Necessites ajuda?", "See the documentation" : "Consulti la documentació", + "Hey there,

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

" : "Ei,

només fer-vos saber que %s us ha comparti %s.
Mireu-ho!", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Aquesta aplicació requereix Javascript per al seu correcte funcionament . Per favor, {linkstart}habiliti Javascript{linkend} i torni a carregar la pàgina.", "Log out" : "Surt", "Search" : "Cerca", @@ -241,13 +242,11 @@ "Log in" : "Inici de sessió", "Wrong password. Reset it?" : "Contrasenya incorrecta. Voleu restablir-la?", "Alternative Logins" : "Acreditacions alternatives", - "Hey there,

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

" : "Ei,

només fer-vos saber que %s us ha comparti %s.
Mireu-ho!", "This ownCloud instance is currently in single user mode." : "La instància ownCloud està en mode d'usuari únic.", "This means only administrators can use the instance." : "Això significa que només els administradors poden usar la instància.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacteu amb l'administrador del sistema si aquest missatge persisteix o apareix inesperadament.", "Thank you for your patience." : "Gràcies per la paciència.", "You are accessing the server from an untrusted domain." : "Esteu accedint al servidor des d'un domini no fiable", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contacteu amb l'administrador. Si sou un administrador d'aquesta instància, configureu el paràmetre \"trusted_domain\" a config/config.php. Hi ha un exemple de configuració a config/config.sampe.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En funció de la teva configuració, com a administrador podries utilitzar el botó d'abaix per confiar en aquest domini.", "Add \"%s\" as trusted domain" : "Afegeix \"%s\" com a domini de confiança", "App update required" : "Cal que actualitzeu la aplicació", diff --git a/core/l10n/cs_CZ.js b/core/l10n/cs_CZ.js index ff173b8e06e..086b100f0b4 100644 --- a/core/l10n/cs_CZ.js +++ b/core/l10n/cs_CZ.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktujte prosím správce systému, pokud se tato zpráva objevuje opakovaně nebo nečekaně.", "Thank you for your patience." : "Děkujeme za vaši trpělivost.", "You are accessing the server from an untrusted domain." : "Přistupujete na server z nedůvěryhodné domény.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kontaktujte prosím správce. Pokud jste správce této instalace, nastavte \"trusted_domain\" v souboru config/config.php. Příklad konfigurace najdete v souboru config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "V závislosti na vaší konfiguraci vám může být, jako správci, umožněno použití tlačítka níže k označení této domény jako důvěryhodné.", "Add \"%s\" as trusted domain" : "Přidat \"%s\" jako důvěryhodnou doménu", "App update required" : "Vyžadována aktualizace aplikace", diff --git a/core/l10n/cs_CZ.json b/core/l10n/cs_CZ.json index a13624e2c18..8f6430785a5 100644 --- a/core/l10n/cs_CZ.json +++ b/core/l10n/cs_CZ.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktujte prosím správce systému, pokud se tato zpráva objevuje opakovaně nebo nečekaně.", "Thank you for your patience." : "Děkujeme za vaši trpělivost.", "You are accessing the server from an untrusted domain." : "Přistupujete na server z nedůvěryhodné domény.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kontaktujte prosím správce. Pokud jste správce této instalace, nastavte \"trusted_domain\" v souboru config/config.php. Příklad konfigurace najdete v souboru config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "V závislosti na vaší konfiguraci vám může být, jako správci, umožněno použití tlačítka níže k označení této domény jako důvěryhodné.", "Add \"%s\" as trusted domain" : "Přidat \"%s\" jako důvěryhodnou doménu", "App update required" : "Vyžadována aktualizace aplikace", diff --git a/core/l10n/da.js b/core/l10n/da.js index 795dc5cb7b9..eed02acd3be 100644 --- a/core/l10n/da.js +++ b/core/l10n/da.js @@ -268,7 +268,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakt systemadministratoren, hvis denne meddelelse fortsætter eller optrådte uventet.", "Thank you for your patience." : "Tak for din tålmodighed.", "You are accessing the server from an untrusted domain." : "Du tilgår serveren fra et utroværdigt domæne", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kontakt venligst din administrator. Hvis du er administrator, konfigurer \"trusted_domain\" indstillingen i config/config.php. Et eksempel kan ses i config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Afhænger af din konfiguration, da du som administrator eventuelt også er i stand til at gøre brug af knappen nedenfor til at tildele tillid til dette domæne.", "Add \"%s\" as trusted domain" : "Tilføj \"%s\" som et troværdigt domæne", "App update required" : "Opdatering af app påkræves", diff --git a/core/l10n/da.json b/core/l10n/da.json index f4f156a69be..35aff828922 100644 --- a/core/l10n/da.json +++ b/core/l10n/da.json @@ -266,7 +266,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakt systemadministratoren, hvis denne meddelelse fortsætter eller optrådte uventet.", "Thank you for your patience." : "Tak for din tålmodighed.", "You are accessing the server from an untrusted domain." : "Du tilgår serveren fra et utroværdigt domæne", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kontakt venligst din administrator. Hvis du er administrator, konfigurer \"trusted_domain\" indstillingen i config/config.php. Et eksempel kan ses i config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Afhænger af din konfiguration, da du som administrator eventuelt også er i stand til at gøre brug af knappen nedenfor til at tildele tillid til dette domæne.", "Add \"%s\" as trusted domain" : "Tilføj \"%s\" som et troværdigt domæne", "App update required" : "Opdatering af app påkræves", diff --git a/core/l10n/de.js b/core/l10n/de.js index 5e02f069e77..0580f88d33b 100644 --- a/core/l10n/de.js +++ b/core/l10n/de.js @@ -242,6 +242,7 @@ OC.L10N.register( "Finishing …" : "Abschließen…", "Need help?" : "Hilfe nötig?", "See the documentation" : "Schau in die Dokumentation", + "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Dir geteilt hat.
Sieh es Dir an!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Diese Anwendung benötigt zum ordnungsgemäßen Betrieb JavaScript. Bitte {linkstart}aktiviere JavaScript{linkend} und lade die Seite neu.", "Log out" : "Abmelden", "Search" : "Suche", @@ -252,13 +253,11 @@ OC.L10N.register( "Log in" : "Anmelden", "Wrong password. Reset it?" : "Falsches Passwort. Soll es zurückgesetzt werden?", "Alternative Logins" : "Alternative Logins", - "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Dir geteilt hat.
Sieh es Dir an!

", "This ownCloud instance is currently in single user mode." : "Diese ownClound-Instanz befindet sich derzeit im Einzelbenutzermodus.", "This means only administrators can use the instance." : "Dies bedeutet, dass diese Instanz nur von Administratoren genutzt werden kann.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktiere Deinen Systemadministrator, wenn diese Meldung dauerhaft oder unerwartet erscheint.", "Thank you for your patience." : "Vielen Dank für Deine Geduld.", "You are accessing the server from an untrusted domain." : "Du greifst von einer nicht vertrauenswürdigen Domain auf den Server zu.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Bitte kontaktiere Deinen Administrator. Wenn Du Administrator dieser Instanz bist, konfiguriere bitte die „trusted_domain“-Einstellung in config/config.php. Eine Beispielkonfiguration wird unter config/config.sample.php bereitgestellt.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Wenn es Deine Konfiguration zulässt, kannst Du als Administrator gegebenenfalls den Button unten benutzen, um diese Domain als vertrauenswürdig einzustufen.", "Add \"%s\" as trusted domain" : "„%s“ als vertrauenswürdige Domain hinzufügen", "App update required" : "Appupdate notwendig", diff --git a/core/l10n/de.json b/core/l10n/de.json index 014cf7fbdf8..285d38429e7 100644 --- a/core/l10n/de.json +++ b/core/l10n/de.json @@ -240,6 +240,7 @@ "Finishing …" : "Abschließen…", "Need help?" : "Hilfe nötig?", "See the documentation" : "Schau in die Dokumentation", + "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Dir geteilt hat.
Sieh es Dir an!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Diese Anwendung benötigt zum ordnungsgemäßen Betrieb JavaScript. Bitte {linkstart}aktiviere JavaScript{linkend} und lade die Seite neu.", "Log out" : "Abmelden", "Search" : "Suche", @@ -250,13 +251,11 @@ "Log in" : "Anmelden", "Wrong password. Reset it?" : "Falsches Passwort. Soll es zurückgesetzt werden?", "Alternative Logins" : "Alternative Logins", - "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Dir geteilt hat.
Sieh es Dir an!

", "This ownCloud instance is currently in single user mode." : "Diese ownClound-Instanz befindet sich derzeit im Einzelbenutzermodus.", "This means only administrators can use the instance." : "Dies bedeutet, dass diese Instanz nur von Administratoren genutzt werden kann.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktiere Deinen Systemadministrator, wenn diese Meldung dauerhaft oder unerwartet erscheint.", "Thank you for your patience." : "Vielen Dank für Deine Geduld.", "You are accessing the server from an untrusted domain." : "Du greifst von einer nicht vertrauenswürdigen Domain auf den Server zu.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Bitte kontaktiere Deinen Administrator. Wenn Du Administrator dieser Instanz bist, konfiguriere bitte die „trusted_domain“-Einstellung in config/config.php. Eine Beispielkonfiguration wird unter config/config.sample.php bereitgestellt.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Wenn es Deine Konfiguration zulässt, kannst Du als Administrator gegebenenfalls den Button unten benutzen, um diese Domain als vertrauenswürdig einzustufen.", "Add \"%s\" as trusted domain" : "„%s“ als vertrauenswürdige Domain hinzufügen", "App update required" : "Appupdate notwendig", diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js index 014b257c972..8dd5132dcd9 100644 --- a/core/l10n/de_DE.js +++ b/core/l10n/de_DE.js @@ -240,6 +240,7 @@ OC.L10N.register( "Finishing …" : "Abschließen…", "Need help?" : "Hilfe nötig?", "See the documentation" : "Schauen Sie in die Dokumentation", + "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Ihnen geteilt hat.
Sehen Sie es sich an!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Diese Anwendung benötigt zum ordnungsgemäßen Betrieb JavaScript. Bitte {linkstart}aktivieren Sie JavaScript{linkend} und laden Sie die Seite neu.", "Log out" : "Abmelden", "Search" : "Suche", @@ -250,13 +251,11 @@ OC.L10N.register( "Log in" : "Einloggen", "Wrong password. Reset it?" : "Falsches Passwort. Soll es zurückgesetzt werden?", "Alternative Logins" : "Alternative Logins", - "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Ihnen geteilt hat.
Sehen Sie es sich an!

", "This ownCloud instance is currently in single user mode." : "Diese ownClound-Instanz befindet sich derzeit im Einzelbenutzermodus.", "This means only administrators can use the instance." : "Das bedeutet, dass diese Instanz nur von Administratoren benutzt werden kann.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktieren Sie Ihren Systemadministrator, wenn diese Meldung dauerhaft oder unerwartet erscheint.", "Thank you for your patience." : "Vielen Dank für Ihre Geduld.", "You are accessing the server from an untrusted domain." : "Sie greifen von einer nicht vertrauenswürdigen Domain auf den Server zu.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Bitte kontaktieren Sie Ihren Administrator. Wenn Sie Administrator dieser Instanz sind, konfigurieren Sie bitte die „trusted_domain“-Einstellung in config/config.php. Eine Beispielkonfiguration wird unter config/config.sample.php bereitgestellt.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Wenn es Ihre Konfiguration zulässt, können Sie als Administrator gegebenenfalls den Button unten benutzen, um diese Domain als vertrauenswürdig einzustufen.", "Add \"%s\" as trusted domain" : "„%s“ als vertrauenswürdige Domain hinzufügen", "App update required" : "App-Update notwendig", diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json index 8ab4fc0c8a2..a1b4a6e72d7 100644 --- a/core/l10n/de_DE.json +++ b/core/l10n/de_DE.json @@ -238,6 +238,7 @@ "Finishing …" : "Abschließen…", "Need help?" : "Hilfe nötig?", "See the documentation" : "Schauen Sie in die Dokumentation", + "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Ihnen geteilt hat.
Sehen Sie es sich an!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Diese Anwendung benötigt zum ordnungsgemäßen Betrieb JavaScript. Bitte {linkstart}aktivieren Sie JavaScript{linkend} und laden Sie die Seite neu.", "Log out" : "Abmelden", "Search" : "Suche", @@ -248,13 +249,11 @@ "Log in" : "Einloggen", "Wrong password. Reset it?" : "Falsches Passwort. Soll es zurückgesetzt werden?", "Alternative Logins" : "Alternative Logins", - "Hey there,

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

" : "Hallo,

hier nur kurz die Mitteilung, dass %s %s mit Ihnen geteilt hat.
Sehen Sie es sich an!

", "This ownCloud instance is currently in single user mode." : "Diese ownClound-Instanz befindet sich derzeit im Einzelbenutzermodus.", "This means only administrators can use the instance." : "Das bedeutet, dass diese Instanz nur von Administratoren benutzt werden kann.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktieren Sie Ihren Systemadministrator, wenn diese Meldung dauerhaft oder unerwartet erscheint.", "Thank you for your patience." : "Vielen Dank für Ihre Geduld.", "You are accessing the server from an untrusted domain." : "Sie greifen von einer nicht vertrauenswürdigen Domain auf den Server zu.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Bitte kontaktieren Sie Ihren Administrator. Wenn Sie Administrator dieser Instanz sind, konfigurieren Sie bitte die „trusted_domain“-Einstellung in config/config.php. Eine Beispielkonfiguration wird unter config/config.sample.php bereitgestellt.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Wenn es Ihre Konfiguration zulässt, können Sie als Administrator gegebenenfalls den Button unten benutzen, um diese Domain als vertrauenswürdig einzustufen.", "Add \"%s\" as trusted domain" : "„%s“ als vertrauenswürdige Domain hinzufügen", "App update required" : "App-Update notwendig", diff --git a/core/l10n/el.js b/core/l10n/el.js index b0a8230e650..b4a4b2efef7 100644 --- a/core/l10n/el.js +++ b/core/l10n/el.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Επικοινωνήστε με το διαχειριστή του συστήματος αν αυτό το μήνυμα συνεχίζει να εμφανίζεται ή εμφανίστηκε απρόσμενα.", "Thank you for your patience." : "Σας ευχαριστούμε για την υπομονή σας.", "You are accessing the server from an untrusted domain." : "Η προσπέλαση του διακομιστή γίνεται από μη έμπιστο τομέα.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Παρακαλώ επικοινωνήστε με τον διαχειριστή συστημάτων σας. Αν είστε διαχειριστής αυτού του στιγμιοτύπο, ρυθμίστε το κλειδί \"trusted_domain\" στο αρχείο config/config.php. Ένα παράδειγμα παρέχεται στο αρχείο config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ανάλογα με τις ρυθμίσεις σας, σαν διαχειριστής θα μπορούσατε επίσης να χρησιμοποιήσετε το παρακάτω κουμπί για να εμπιστευθείτε αυτή την περιοχή.", "Add \"%s\" as trusted domain" : "Προσθήκη \"%s\" ως αξιόπιστη περιοχή", "App update required" : "Απαιτείται ενημέρωση εφαρμογής", diff --git a/core/l10n/el.json b/core/l10n/el.json index f2e4430f2db..dfa81965cbc 100644 --- a/core/l10n/el.json +++ b/core/l10n/el.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Επικοινωνήστε με το διαχειριστή του συστήματος αν αυτό το μήνυμα συνεχίζει να εμφανίζεται ή εμφανίστηκε απρόσμενα.", "Thank you for your patience." : "Σας ευχαριστούμε για την υπομονή σας.", "You are accessing the server from an untrusted domain." : "Η προσπέλαση του διακομιστή γίνεται από μη έμπιστο τομέα.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Παρακαλώ επικοινωνήστε με τον διαχειριστή συστημάτων σας. Αν είστε διαχειριστής αυτού του στιγμιοτύπο, ρυθμίστε το κλειδί \"trusted_domain\" στο αρχείο config/config.php. Ένα παράδειγμα παρέχεται στο αρχείο config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ανάλογα με τις ρυθμίσεις σας, σαν διαχειριστής θα μπορούσατε επίσης να χρησιμοποιήσετε το παρακάτω κουμπί για να εμπιστευθείτε αυτή την περιοχή.", "Add \"%s\" as trusted domain" : "Προσθήκη \"%s\" ως αξιόπιστη περιοχή", "App update required" : "Απαιτείται ενημέρωση εφαρμογής", diff --git a/core/l10n/en_GB.js b/core/l10n/en_GB.js index d9fe9ab7671..e8c85405d16 100644 --- a/core/l10n/en_GB.js +++ b/core/l10n/en_GB.js @@ -218,6 +218,7 @@ OC.L10N.register( "Finishing …" : "Finishing …", "Need help?" : "Need help?", "See the documentation" : "See the documentation", + "Hey there,

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

" : "Hey there,

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

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page.", "Log out" : "Log out", "Search" : "Search", @@ -227,13 +228,11 @@ OC.L10N.register( "Please try again or contact your administrator." : "Please try again or contact your administrator.", "Log in" : "Log in", "Alternative Logins" : "Alternative Logins", - "Hey there,

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

" : "Hey there,

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

", "This ownCloud instance is currently in single user mode." : "This ownCloud instance is currently in single user mode.", "This means only administrators can use the instance." : "This means only administrators can use the instance.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contact your system administrator if this message persists or appeared unexpectedly.", "Thank you for your patience." : "Thank you for your patience.", "You are accessing the server from an untrusted domain." : "You are accessing the server from an untrusted domain.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain.", "Add \"%s\" as trusted domain" : "Add \"%s\" as a trusted domain", "The theme %s has been disabled." : "The theme %s has been disabled.", diff --git a/core/l10n/en_GB.json b/core/l10n/en_GB.json index c3a77a88047..1a2c794895a 100644 --- a/core/l10n/en_GB.json +++ b/core/l10n/en_GB.json @@ -216,6 +216,7 @@ "Finishing …" : "Finishing …", "Need help?" : "Need help?", "See the documentation" : "See the documentation", + "Hey there,

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

" : "Hey there,

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

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page.", "Log out" : "Log out", "Search" : "Search", @@ -225,13 +226,11 @@ "Please try again or contact your administrator." : "Please try again or contact your administrator.", "Log in" : "Log in", "Alternative Logins" : "Alternative Logins", - "Hey there,

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

" : "Hey there,

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

", "This ownCloud instance is currently in single user mode." : "This ownCloud instance is currently in single user mode.", "This means only administrators can use the instance." : "This means only administrators can use the instance.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contact your system administrator if this message persists or appeared unexpectedly.", "Thank you for your patience." : "Thank you for your patience.", "You are accessing the server from an untrusted domain." : "You are accessing the server from an untrusted domain.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain.", "Add \"%s\" as trusted domain" : "Add \"%s\" as a trusted domain", "The theme %s has been disabled." : "The theme %s has been disabled.", diff --git a/core/l10n/es.js b/core/l10n/es.js index 774ff7ef9d2..316f938798d 100644 --- a/core/l10n/es.js +++ b/core/l10n/es.js @@ -263,7 +263,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte con su administrador de sistemas si este mensaje persiste o aparece de forma inesperada.", "Thank you for your patience." : "Gracias por su paciencia.", "You are accessing the server from an untrusted domain." : "Está accediendo al servidor desde un dominio inseguro.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contacte con su administrador. Si usted es el administrador, configure \"trusted_domain\" en config/config.php. En config/config.sample.php se encuentra un ejemplo para la configuración.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependiendo de su configuración, como administrador, debería poder usar el botón de abajo para confiar en este dominio.", "Add \"%s\" as trusted domain" : "Agregar \"%s\" como dominio de confianza", "App update required" : "Es necesaria una actualización en la aplicación", diff --git a/core/l10n/es.json b/core/l10n/es.json index 850e82d4195..aa865fbd542 100644 --- a/core/l10n/es.json +++ b/core/l10n/es.json @@ -261,7 +261,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte con su administrador de sistemas si este mensaje persiste o aparece de forma inesperada.", "Thank you for your patience." : "Gracias por su paciencia.", "You are accessing the server from an untrusted domain." : "Está accediendo al servidor desde un dominio inseguro.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contacte con su administrador. Si usted es el administrador, configure \"trusted_domain\" en config/config.php. En config/config.sample.php se encuentra un ejemplo para la configuración.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependiendo de su configuración, como administrador, debería poder usar el botón de abajo para confiar en este dominio.", "Add \"%s\" as trusted domain" : "Agregar \"%s\" como dominio de confianza", "App update required" : "Es necesaria una actualización en la aplicación", diff --git a/core/l10n/es_CL.js b/core/l10n/es_CL.js index 33de74ee9ee..46e2ece071d 100644 --- a/core/l10n/es_CL.js +++ b/core/l10n/es_CL.js @@ -42,7 +42,6 @@ OC.L10N.register( "Admin" : "Administración", "Help" : "Ayuda", "Username" : "Usuario", - "You are accessing the server from an untrusted domain." : "Usted está accediendo al servidor desde un dominio no confiable.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor contacte con su administrador. Si usted es el administrador de esta instancia, configure la opción \"trusted_domain\" en \"config/config.php\". Un ejemplo de la configuración está disponible en config/config.sample.php" + "You are accessing the server from an untrusted domain." : "Usted está accediendo al servidor desde un dominio no confiable." }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/es_CL.json b/core/l10n/es_CL.json index 58346c15741..ffddc11b753 100644 --- a/core/l10n/es_CL.json +++ b/core/l10n/es_CL.json @@ -40,7 +40,6 @@ "Admin" : "Administración", "Help" : "Ayuda", "Username" : "Usuario", - "You are accessing the server from an untrusted domain." : "Usted está accediendo al servidor desde un dominio no confiable.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor contacte con su administrador. Si usted es el administrador de esta instancia, configure la opción \"trusted_domain\" en \"config/config.php\". Un ejemplo de la configuración está disponible en config/config.sample.php" + "You are accessing the server from an untrusted domain." : "Usted está accediendo al servidor desde un dominio no confiable." },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/core/l10n/et_EE.js b/core/l10n/et_EE.js index 8ffb70516a6..b782b43999a 100644 --- a/core/l10n/et_EE.js +++ b/core/l10n/et_EE.js @@ -218,6 +218,7 @@ OC.L10N.register( "Finishing …" : "Lõpetamine ...", "Need help?" : "Vajad abi?", "See the documentation" : "Vaata dokumentatsiooni", + "Hey there,

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

" : "Hei,

annan teada, et %s jagas sinuga %s. Vaata seda!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "See rakendus vajab toimimiseks JavaScripti. Palun {linkstart}luba JavaScript{linkend} ning laadi see leht uuesti.", "Log out" : "Logi välja", "Search" : "Otsi", @@ -227,13 +228,11 @@ OC.L10N.register( "Please try again or contact your administrator." : "Palun proovi uuesti või võta ühendust oma administraatoriga.", "Log in" : "Logi sisse", "Alternative Logins" : "Alternatiivsed sisselogimisviisid", - "Hey there,

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

" : "Hei,

annan teada, et %s jagas sinuga %s. Vaata seda!

", "This ownCloud instance is currently in single user mode." : "See ownCloud on momendil seadistatud ühe kasutaja jaoks.", "This means only administrators can use the instance." : "See tähendab, et seda saavad kasutada ainult administraatorid.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakteeru oma süsteemihalduriga, kui see teade püsib või on tekkinud ootamatult.", "Thank you for your patience." : "Täname kannatlikkuse eest.", "You are accessing the server from an untrusted domain." : "Sa kasutad serverit usalduseta asukohast", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Palun võta ühendust oma saidi administraatoriga. Kui sa oled ise administraator, siis seadista failis config/config.php sätet \"trusted_domain\". Näidis seadistused leiad failist config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Sõltuvalt sinu seadetest võib ka administraator kasutada allolevat nuppu, et seda domeeni usaldusväärseks märkida.", "Add \"%s\" as trusted domain" : "Lisa \"%s\" usaldusväärse domeenina", "App update required" : "Rakenduse uuendus on nõutud", diff --git a/core/l10n/et_EE.json b/core/l10n/et_EE.json index 000e38e7053..c25b9f166c9 100644 --- a/core/l10n/et_EE.json +++ b/core/l10n/et_EE.json @@ -216,6 +216,7 @@ "Finishing …" : "Lõpetamine ...", "Need help?" : "Vajad abi?", "See the documentation" : "Vaata dokumentatsiooni", + "Hey there,

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

" : "Hei,

annan teada, et %s jagas sinuga %s. Vaata seda!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "See rakendus vajab toimimiseks JavaScripti. Palun {linkstart}luba JavaScript{linkend} ning laadi see leht uuesti.", "Log out" : "Logi välja", "Search" : "Otsi", @@ -225,13 +226,11 @@ "Please try again or contact your administrator." : "Palun proovi uuesti või võta ühendust oma administraatoriga.", "Log in" : "Logi sisse", "Alternative Logins" : "Alternatiivsed sisselogimisviisid", - "Hey there,

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

" : "Hei,

annan teada, et %s jagas sinuga %s. Vaata seda!

", "This ownCloud instance is currently in single user mode." : "See ownCloud on momendil seadistatud ühe kasutaja jaoks.", "This means only administrators can use the instance." : "See tähendab, et seda saavad kasutada ainult administraatorid.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakteeru oma süsteemihalduriga, kui see teade püsib või on tekkinud ootamatult.", "Thank you for your patience." : "Täname kannatlikkuse eest.", "You are accessing the server from an untrusted domain." : "Sa kasutad serverit usalduseta asukohast", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Palun võta ühendust oma saidi administraatoriga. Kui sa oled ise administraator, siis seadista failis config/config.php sätet \"trusted_domain\". Näidis seadistused leiad failist config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Sõltuvalt sinu seadetest võib ka administraator kasutada allolevat nuppu, et seda domeeni usaldusväärseks märkida.", "Add \"%s\" as trusted domain" : "Lisa \"%s\" usaldusväärse domeenina", "App update required" : "Rakenduse uuendus on nõutud", diff --git a/core/l10n/eu.js b/core/l10n/eu.js index 4b62ef72bf8..d24a7cd42e2 100644 --- a/core/l10n/eu.js +++ b/core/l10n/eu.js @@ -192,19 +192,18 @@ OC.L10N.register( "Database host" : "Datubasearen hostalaria", "Finish setup" : "Bukatu konfigurazioa", "Finishing …" : "Bukatzen...", + "Hey there,

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

" : "Kaixo

%s-ek %s zurekin partekatu duela jakin dezazun.\nIkusi ezazu: %s", "Log out" : "Saioa bukatu", "Search" : "Bilatu", "Server side authentication failed!" : "Zerbitzari aldeko autentifikazioak huts egin du!", "Please contact your administrator." : "Mesedez jarri harremetan zure administradorearekin.", "Log in" : "Hasi saioa", "Alternative Logins" : "Beste erabiltzaile izenak", - "Hey there,

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

" : "Kaixo

%s-ek %s zurekin partekatu duela jakin dezazun.\nIkusi ezazu: %s", "This ownCloud instance is currently in single user mode." : "ownCloud instantzia hau erabiltzaile bakar moduan dago.", "This means only administrators can use the instance." : "Honek administradoreak bakarrik erabili dezakeela esan nahi du.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Jarri harremanetan zure sistema administratzailearekin mezu hau irauten badu edo bat-batean agertu bada.", "Thank you for your patience." : "Milesker zure patzientziagatik.", "You are accessing the server from an untrusted domain." : "Zerbitzaria domeinu ez fidagarri batetik eskuratzen ari zara.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Mesedez harremanetan jarri kudeatzailearekin. Zu kudeatzailea bazara, konfiguratu \"trusted_domain\" ezarpena config/config.php fitxategian. Adibidezko konfigurazko bat config/config.sample.php fitxategian dago.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Zure ezarpenen gorabehera, administratzaile bezala posible duzu ere azpiko botoia erabiltzea fidatzeko domeinu horrekin.", "Add \"%s\" as trusted domain" : "Gehitu \"%s\" domeinu fidagarri gisa", "The theme %s has been disabled." : "%s gaia desgaitu da.", diff --git a/core/l10n/eu.json b/core/l10n/eu.json index 8437059bf3a..81849897490 100644 --- a/core/l10n/eu.json +++ b/core/l10n/eu.json @@ -190,19 +190,18 @@ "Database host" : "Datubasearen hostalaria", "Finish setup" : "Bukatu konfigurazioa", "Finishing …" : "Bukatzen...", + "Hey there,

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

" : "Kaixo

%s-ek %s zurekin partekatu duela jakin dezazun.\nIkusi ezazu: %s", "Log out" : "Saioa bukatu", "Search" : "Bilatu", "Server side authentication failed!" : "Zerbitzari aldeko autentifikazioak huts egin du!", "Please contact your administrator." : "Mesedez jarri harremetan zure administradorearekin.", "Log in" : "Hasi saioa", "Alternative Logins" : "Beste erabiltzaile izenak", - "Hey there,

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

" : "Kaixo

%s-ek %s zurekin partekatu duela jakin dezazun.\nIkusi ezazu: %s", "This ownCloud instance is currently in single user mode." : "ownCloud instantzia hau erabiltzaile bakar moduan dago.", "This means only administrators can use the instance." : "Honek administradoreak bakarrik erabili dezakeela esan nahi du.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Jarri harremanetan zure sistema administratzailearekin mezu hau irauten badu edo bat-batean agertu bada.", "Thank you for your patience." : "Milesker zure patzientziagatik.", "You are accessing the server from an untrusted domain." : "Zerbitzaria domeinu ez fidagarri batetik eskuratzen ari zara.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Mesedez harremanetan jarri kudeatzailearekin. Zu kudeatzailea bazara, konfiguratu \"trusted_domain\" ezarpena config/config.php fitxategian. Adibidezko konfigurazko bat config/config.sample.php fitxategian dago.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Zure ezarpenen gorabehera, administratzaile bezala posible duzu ere azpiko botoia erabiltzea fidatzeko domeinu horrekin.", "Add \"%s\" as trusted domain" : "Gehitu \"%s\" domeinu fidagarri gisa", "The theme %s has been disabled." : "%s gaia desgaitu da.", diff --git a/core/l10n/fi_FI.js b/core/l10n/fi_FI.js index c5104a9a1d0..28b9c98db67 100644 --- a/core/l10n/fi_FI.js +++ b/core/l10n/fi_FI.js @@ -252,6 +252,7 @@ OC.L10N.register( "Finishing …" : "Valmistellaan…", "Need help?" : "Tarvitsetko apua?", "See the documentation" : "Tutustu dokumentaatioon", + "Hey there,

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

" : "Hei!

%s jakoi kanssasi kohteen %s.
Tutustu siihen!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Tämä sovellus vaatii toimiakseen JavaScript-tuen. {linkstart}Ota JavaScript käyttöön{linkend} ja päivitä sivu.", "Log out" : "Kirjaudu ulos", "Search" : "Etsi", @@ -263,13 +264,11 @@ OC.L10N.register( "Wrong password. Reset it?" : "Väärä salasana. Haluatko palauttaa salasanan?", "Stay logged in" : "Pysy sisäänkirjautuneena", "Alternative Logins" : "Vaihtoehtoiset kirjautumiset", - "Hey there,

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

" : "Hei!

%s jakoi kanssasi kohteen %s.
Tutustu siihen!

", "This ownCloud instance is currently in single user mode." : "Tämä ownCloud-asennus on parhaillaan single user -tilassa.", "This means only administrators can use the instance." : "Se tarkoittaa, että vain ylläpitäjät voivat nyt käyttää tätä ownCloudia.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Ota yhteys järjestelmän ylläpitäjään, jos tämä viesti ilmenee uudelleen tai odottamatta.", "Thank you for your patience." : "Kiitos kärsivällisyydestäsi.", "You are accessing the server from an untrusted domain." : "Olet yhteydessä palvelimeen epäluotettavasta verkko-osoitteesta.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Ota yhteys ylläpitäjään. Jos olet tämän ownCloudin ylläpitäjä, määritä \"trusted_domain\"-asetus tiedostossa config/config.php. Esimerkkimääritys on nähtävillä tiedostossa config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Riippuen määrityksistä, ylläpitäjänä saatat kyetä käyttämään alla olevaa painiketta luodaksesi luottamussuhteen tähän toimialueeseen.", "Add \"%s\" as trusted domain" : "Lisää \"%s\" luotetuksi toimialueeksi", "App update required" : "Sovelluksen päivittäminen vaaditaan", diff --git a/core/l10n/fi_FI.json b/core/l10n/fi_FI.json index a10487412ea..1a84873e6cc 100644 --- a/core/l10n/fi_FI.json +++ b/core/l10n/fi_FI.json @@ -250,6 +250,7 @@ "Finishing …" : "Valmistellaan…", "Need help?" : "Tarvitsetko apua?", "See the documentation" : "Tutustu dokumentaatioon", + "Hey there,

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

" : "Hei!

%s jakoi kanssasi kohteen %s.
Tutustu siihen!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Tämä sovellus vaatii toimiakseen JavaScript-tuen. {linkstart}Ota JavaScript käyttöön{linkend} ja päivitä sivu.", "Log out" : "Kirjaudu ulos", "Search" : "Etsi", @@ -261,13 +262,11 @@ "Wrong password. Reset it?" : "Väärä salasana. Haluatko palauttaa salasanan?", "Stay logged in" : "Pysy sisäänkirjautuneena", "Alternative Logins" : "Vaihtoehtoiset kirjautumiset", - "Hey there,

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

" : "Hei!

%s jakoi kanssasi kohteen %s.
Tutustu siihen!

", "This ownCloud instance is currently in single user mode." : "Tämä ownCloud-asennus on parhaillaan single user -tilassa.", "This means only administrators can use the instance." : "Se tarkoittaa, että vain ylläpitäjät voivat nyt käyttää tätä ownCloudia.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Ota yhteys järjestelmän ylläpitäjään, jos tämä viesti ilmenee uudelleen tai odottamatta.", "Thank you for your patience." : "Kiitos kärsivällisyydestäsi.", "You are accessing the server from an untrusted domain." : "Olet yhteydessä palvelimeen epäluotettavasta verkko-osoitteesta.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Ota yhteys ylläpitäjään. Jos olet tämän ownCloudin ylläpitäjä, määritä \"trusted_domain\"-asetus tiedostossa config/config.php. Esimerkkimääritys on nähtävillä tiedostossa config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Riippuen määrityksistä, ylläpitäjänä saatat kyetä käyttämään alla olevaa painiketta luodaksesi luottamussuhteen tähän toimialueeseen.", "Add \"%s\" as trusted domain" : "Lisää \"%s\" luotetuksi toimialueeksi", "App update required" : "Sovelluksen päivittäminen vaaditaan", diff --git a/core/l10n/fr.js b/core/l10n/fr.js index 98a0128775b..e25840a7afc 100644 --- a/core/l10n/fr.js +++ b/core/l10n/fr.js @@ -269,7 +269,6 @@ 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.", "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_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Veuillez contacter votre administrateur. Si vous êtes administrateur de cette instance, configurez le paramètre « trusted_domain » dans le fichier config/config.php. Un exemple de configuration est fourni dans le fichier config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En fonction de votre configuration, en tant qu'administrateur vous pouvez également utiliser le bouton ci-dessous pour approuver ce domaine.", "Add \"%s\" as trusted domain" : "Ajouter \"%s\" à la liste des domaines approuvés", "App update required" : "Mise à jour de l'application nécessaire", diff --git a/core/l10n/fr.json b/core/l10n/fr.json index b1672b90a2d..0d86fa37d5a 100644 --- a/core/l10n/fr.json +++ b/core/l10n/fr.json @@ -267,7 +267,6 @@ "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.", "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_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Veuillez contacter votre administrateur. Si vous êtes administrateur de cette instance, configurez le paramètre « trusted_domain » dans le fichier config/config.php. Un exemple de configuration est fourni dans le fichier config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En fonction de votre configuration, en tant qu'administrateur vous pouvez également utiliser le bouton ci-dessous pour approuver ce domaine.", "Add \"%s\" as trusted domain" : "Ajouter \"%s\" à la liste des domaines approuvés", "App update required" : "Mise à jour de l'application nécessaire", diff --git a/core/l10n/gl.js b/core/l10n/gl.js index 18b95168327..92fa9a74f35 100644 --- a/core/l10n/gl.js +++ b/core/l10n/gl.js @@ -231,6 +231,7 @@ OC.L10N.register( "Finishing …" : "Rematando ...", "Need help?" : "Precisa axuda?", "See the documentation" : "Vexa a documentación", + "Hey there,

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

" : "Ola,

só facerlle saber que %s compartiu %s con vostede.
Véxao!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Esta aplicación require JavaScript para un correcto funcionamento. {linkstart}Active JavaScript{linkend} e volva cargar a páxina.", "Log out" : "Desconectar", "Search" : "Buscar", @@ -240,13 +241,11 @@ OC.L10N.register( "Please try again or contact your administrator." : "Ténteo de novo ou póñase en contacto co administrador.", "Log in" : "Acceder", "Alternative Logins" : "Accesos alternativos", - "Hey there,

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

" : "Ola,

só facerlle saber que %s compartiu %s con vostede.
Véxao!

", "This ownCloud instance is currently in single user mode." : "Esta instancia do ownCloud está actualmente en modo de usuario único.", "This means only administrators can use the instance." : "Isto significa que só os administradores poden utilizar a instancia.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Póñase en contacto co administrador do sistema se persiste esta mensaxe ou se aparece de forma inesperada.", "Thank you for your patience." : "Grazas pola súa paciencia.", "You are accessing the server from an untrusted domain." : "Esta accedendo desde un dominio non fiábel.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Póñase en contacto co administrador. Se vostede é administrador desta instancia, configure o parámetro «trusted_domain» en config/config.php. Dispón dun exemplo de configuración en config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da súa configuración, como administrador vostede podería utilizar o botón de embaixo para confiar neste dominio.", "Add \"%s\" as trusted domain" : "Engadir «%s» como dominio de confianza", "App update required" : "É necesario actualizar a aplicación", diff --git a/core/l10n/gl.json b/core/l10n/gl.json index bceb4517cf4..ebc7313cccc 100644 --- a/core/l10n/gl.json +++ b/core/l10n/gl.json @@ -229,6 +229,7 @@ "Finishing …" : "Rematando ...", "Need help?" : "Precisa axuda?", "See the documentation" : "Vexa a documentación", + "Hey there,

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

" : "Ola,

só facerlle saber que %s compartiu %s con vostede.
Véxao!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Esta aplicación require JavaScript para un correcto funcionamento. {linkstart}Active JavaScript{linkend} e volva cargar a páxina.", "Log out" : "Desconectar", "Search" : "Buscar", @@ -238,13 +239,11 @@ "Please try again or contact your administrator." : "Ténteo de novo ou póñase en contacto co administrador.", "Log in" : "Acceder", "Alternative Logins" : "Accesos alternativos", - "Hey there,

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

" : "Ola,

só facerlle saber que %s compartiu %s con vostede.
Véxao!

", "This ownCloud instance is currently in single user mode." : "Esta instancia do ownCloud está actualmente en modo de usuario único.", "This means only administrators can use the instance." : "Isto significa que só os administradores poden utilizar a instancia.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Póñase en contacto co administrador do sistema se persiste esta mensaxe ou se aparece de forma inesperada.", "Thank you for your patience." : "Grazas pola súa paciencia.", "You are accessing the server from an untrusted domain." : "Esta accedendo desde un dominio non fiábel.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Póñase en contacto co administrador. Se vostede é administrador desta instancia, configure o parámetro «trusted_domain» en config/config.php. Dispón dun exemplo de configuración en config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da súa configuración, como administrador vostede podería utilizar o botón de embaixo para confiar neste dominio.", "Add \"%s\" as trusted domain" : "Engadir «%s» como dominio de confianza", "App update required" : "É necesario actualizar a aplicación", diff --git a/core/l10n/hr.js b/core/l10n/hr.js index 0cf75a01625..6bb9356a76b 100644 --- a/core/l10n/hr.js +++ b/core/l10n/hr.js @@ -196,19 +196,18 @@ OC.L10N.register( "Database host" : "Glavno računalo baze podataka", "Finish setup" : "Završite postavljanje", "Finishing …" : "Završavanje...", + "Hey there,

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

" : "Hej,

vam upravo javlja da je %s podijelio %ss vama.
POgledajte!

", "Log out" : "Odjavite se", "Search" : "pretraži", "Server side authentication failed!" : "Autentikacija na strani poslužitelja nije uspjela!", "Please contact your administrator." : "Molimo kontaktirajte svog administratora.", "Log in" : "Prijavite se", "Alternative Logins" : "Alternativne prijave", - "Hey there,

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

" : "Hej,

vam upravo javlja da je %s podijelio %ss vama.
POgledajte!

", "This ownCloud instance is currently in single user mode." : "Ova ownCloud instanca je trenutno u načinu rada za jednog korisnika.", "This means only administrators can use the instance." : "To znači da tu instancu mogu koristiti samo administratori.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte svog administratora sustava ako se ova poruka ponavlja ili sepojavila neočekivano.", "Thank you for your patience." : "Hvala vam na strpljenju", "You are accessing the server from an untrusted domain." : "Poslužitelju pristupate iz nepouzdane domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molimo kontaktirajte svog administratora. Ako ste vi administrator ove instance,konfigurirajte postavku \"trusted_domain\" config/config.php.Primjer konfiguracije ponuđen je u config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ovisno o vašoj konfiguraciji, kao administrator vi biste također mogli koristitigumb dolje za pristup toj domeni.", "Add \"%s\" as trusted domain" : "Dodajte \"%s\" kao pouzdanu domenu.", "The theme %s has been disabled." : "Tema %s je onemogućena", diff --git a/core/l10n/hr.json b/core/l10n/hr.json index 5475fe2e45b..3e64259428c 100644 --- a/core/l10n/hr.json +++ b/core/l10n/hr.json @@ -194,19 +194,18 @@ "Database host" : "Glavno računalo baze podataka", "Finish setup" : "Završite postavljanje", "Finishing …" : "Završavanje...", + "Hey there,

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

" : "Hej,

vam upravo javlja da je %s podijelio %ss vama.
POgledajte!

", "Log out" : "Odjavite se", "Search" : "pretraži", "Server side authentication failed!" : "Autentikacija na strani poslužitelja nije uspjela!", "Please contact your administrator." : "Molimo kontaktirajte svog administratora.", "Log in" : "Prijavite se", "Alternative Logins" : "Alternativne prijave", - "Hey there,

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

" : "Hej,

vam upravo javlja da je %s podijelio %ss vama.
POgledajte!

", "This ownCloud instance is currently in single user mode." : "Ova ownCloud instanca je trenutno u načinu rada za jednog korisnika.", "This means only administrators can use the instance." : "To znači da tu instancu mogu koristiti samo administratori.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte svog administratora sustava ako se ova poruka ponavlja ili sepojavila neočekivano.", "Thank you for your patience." : "Hvala vam na strpljenju", "You are accessing the server from an untrusted domain." : "Poslužitelju pristupate iz nepouzdane domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molimo kontaktirajte svog administratora. Ako ste vi administrator ove instance,konfigurirajte postavku \"trusted_domain\" config/config.php.Primjer konfiguracije ponuđen je u config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ovisno o vašoj konfiguraciji, kao administrator vi biste također mogli koristitigumb dolje za pristup toj domeni.", "Add \"%s\" as trusted domain" : "Dodajte \"%s\" kao pouzdanu domenu.", "The theme %s has been disabled." : "Tema %s je onemogućena", diff --git a/core/l10n/hu_HU.js b/core/l10n/hu_HU.js index 52c13fd96cd..0feea423eb6 100644 --- a/core/l10n/hu_HU.js +++ b/core/l10n/hu_HU.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Ha ez az üzenet ismételten vagy indokolatlanul megjelenik, akkor keresse a rendszergazda segítségét!", "Thank you for your patience." : "Köszönjük a türelmét.", "You are accessing the server from an untrusted domain." : "A kiszolgálót nem megbízható tartományból éri el.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kérjük keresse fel a rendszergazdát! Ha ennek a telepítésnek Ön a rendszergazdája, akkor állítsa be a config/config.php állományban a \"trusted_domain\" paramétert! A config/config.sample.php állományban talál példát a beállításra.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "A beállításoktól függően, rendszergazdaként lehetséges, hogy az alábbi gombot is használhatja a tartomány megbízhatóvá tételéhez.", "Add \"%s\" as trusted domain" : "Adjuk hozzá \"%s\"-t a megbízható tartományokhoz!", "App update required" : "Alkalmazás frissítés szükséges", diff --git a/core/l10n/hu_HU.json b/core/l10n/hu_HU.json index 6c48c51b6d3..313be232295 100644 --- a/core/l10n/hu_HU.json +++ b/core/l10n/hu_HU.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Ha ez az üzenet ismételten vagy indokolatlanul megjelenik, akkor keresse a rendszergazda segítségét!", "Thank you for your patience." : "Köszönjük a türelmét.", "You are accessing the server from an untrusted domain." : "A kiszolgálót nem megbízható tartományból éri el.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kérjük keresse fel a rendszergazdát! Ha ennek a telepítésnek Ön a rendszergazdája, akkor állítsa be a config/config.php állományban a \"trusted_domain\" paramétert! A config/config.sample.php állományban talál példát a beállításra.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "A beállításoktól függően, rendszergazdaként lehetséges, hogy az alábbi gombot is használhatja a tartomány megbízhatóvá tételéhez.", "Add \"%s\" as trusted domain" : "Adjuk hozzá \"%s\"-t a megbízható tartományokhoz!", "App update required" : "Alkalmazás frissítés szükséges", diff --git a/core/l10n/id.js b/core/l10n/id.js index 012f762d173..6306d0682e0 100644 --- a/core/l10n/id.js +++ b/core/l10n/id.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Hubungi administrator sistem anda jika pesan ini terus muncul atau muncul tiba-tiba.", "Thank you for your patience." : "Terima kasih atas kesabaran anda.", "You are accessing the server from an untrusted domain." : "Anda mengakses server dari domain yang tidak terpercaya.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Mohon hubungi administrator Anda. Jika Anda seorang administrator dari instansi ini, konfigurasikan pengaturan \"trusted_domain\" didalam config/config.php. Contoh konfigurasi talah disediakan didalam config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Tergantung pada konfigurasi Anda, sebagai seorang administrator Anda kemungkinan dapat menggunakan tombol bawah untuk mempercayai domain ini.", "Add \"%s\" as trusted domain" : "tambahkan \"%s\" sebagai domain terpercaya", "App update required" : "Diperlukan perbarui aplikasi", diff --git a/core/l10n/id.json b/core/l10n/id.json index c78e73522a3..80eebfdaab4 100644 --- a/core/l10n/id.json +++ b/core/l10n/id.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Hubungi administrator sistem anda jika pesan ini terus muncul atau muncul tiba-tiba.", "Thank you for your patience." : "Terima kasih atas kesabaran anda.", "You are accessing the server from an untrusted domain." : "Anda mengakses server dari domain yang tidak terpercaya.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Mohon hubungi administrator Anda. Jika Anda seorang administrator dari instansi ini, konfigurasikan pengaturan \"trusted_domain\" didalam config/config.php. Contoh konfigurasi talah disediakan didalam config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Tergantung pada konfigurasi Anda, sebagai seorang administrator Anda kemungkinan dapat menggunakan tombol bawah untuk mempercayai domain ini.", "Add \"%s\" as trusted domain" : "tambahkan \"%s\" sebagai domain terpercaya", "App update required" : "Diperlukan perbarui aplikasi", diff --git a/core/l10n/is.js b/core/l10n/is.js index 2c744ef1e90..a4f17b74f55 100644 --- a/core/l10n/is.js +++ b/core/l10n/is.js @@ -238,6 +238,7 @@ OC.L10N.register( "Finishing …" : "Að klára ...", "Need help?" : "Þarftu hjálp?", "See the documentation" : "Sjá handbók", + "Hey there,

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

" : "Sælir ,

bara láta þig vita að %s deildi %s með þér.
Skoða það!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Þetta forrit krefst JavaScript fyrir rétta virkni. Vinsamlegast {linkstart} virkjaðu JavaScript {linkend} og endurhladdu síðunni.", "Log out" : "Útskrá", "Search" : "Leita", @@ -248,13 +249,11 @@ OC.L10N.register( "Log in" : "Skrá inn", "Wrong password. Reset it?" : "Rangt lykilorð. Endursetja?", "Alternative Logins" : "Aðrar Innskráningar", - "Hey there,

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

" : "Sælir ,

bara láta þig vita að %s deildi %s með þér.
Skoða það!

", "This ownCloud instance is currently in single user mode." : "Þetta ownCloud eintak er nú í einnar notandaham.", "This means only administrators can use the instance." : "Þetta þýðir aðeins stjórnendur geta notað eintak.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Hafðu samband við kerfisstjóra ef þessi skilaboð eru viðvarandi eða birtist óvænt.", "Thank you for your patience." : "Þakka þér fyrir biðlundina.", "You are accessing the server from an untrusted domain." : "Þú ert að tengjast þjóninum frá ótraustu umdæmi.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Vinsamlegast hafðu samband við kerfisstjóra. Ef þú ert stjórnandi á þessu eintaki, stiltu þá \"trusted_domain\" stillingu í config/config.php. Dæmigerðar stillingar er að finna í config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Það fer eftir stillingum þínum, sem stjórnandi þá gætir þú einnig notað hnappinn hér fyrir neðan til að treysta þessu léni.", "Add \"%s\" as trusted domain" : "Bæta við \"%s\" sem treyst lén", "App update required" : "App þarfnast uppfærslu ", diff --git a/core/l10n/is.json b/core/l10n/is.json index ca7db83d014..aebd0c756d2 100644 --- a/core/l10n/is.json +++ b/core/l10n/is.json @@ -236,6 +236,7 @@ "Finishing …" : "Að klára ...", "Need help?" : "Þarftu hjálp?", "See the documentation" : "Sjá handbók", + "Hey there,

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

" : "Sælir ,

bara láta þig vita að %s deildi %s með þér.
Skoða það!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Þetta forrit krefst JavaScript fyrir rétta virkni. Vinsamlegast {linkstart} virkjaðu JavaScript {linkend} og endurhladdu síðunni.", "Log out" : "Útskrá", "Search" : "Leita", @@ -246,13 +247,11 @@ "Log in" : "Skrá inn", "Wrong password. Reset it?" : "Rangt lykilorð. Endursetja?", "Alternative Logins" : "Aðrar Innskráningar", - "Hey there,

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

" : "Sælir ,

bara láta þig vita að %s deildi %s með þér.
Skoða það!

", "This ownCloud instance is currently in single user mode." : "Þetta ownCloud eintak er nú í einnar notandaham.", "This means only administrators can use the instance." : "Þetta þýðir aðeins stjórnendur geta notað eintak.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Hafðu samband við kerfisstjóra ef þessi skilaboð eru viðvarandi eða birtist óvænt.", "Thank you for your patience." : "Þakka þér fyrir biðlundina.", "You are accessing the server from an untrusted domain." : "Þú ert að tengjast þjóninum frá ótraustu umdæmi.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Vinsamlegast hafðu samband við kerfisstjóra. Ef þú ert stjórnandi á þessu eintaki, stiltu þá \"trusted_domain\" stillingu í config/config.php. Dæmigerðar stillingar er að finna í config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Það fer eftir stillingum þínum, sem stjórnandi þá gætir þú einnig notað hnappinn hér fyrir neðan til að treysta þessu léni.", "Add \"%s\" as trusted domain" : "Bæta við \"%s\" sem treyst lén", "App update required" : "App þarfnast uppfærslu ", diff --git a/core/l10n/it.js b/core/l10n/it.js index 02a288a5647..d95b02b2841 100644 --- a/core/l10n/it.js +++ b/core/l10n/it.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Contatta il tuo amministratore di sistema se questo messaggio persiste o appare inaspettatamente.", "Thank you for your patience." : "Grazie per la pazienza.", "You are accessing the server from an untrusted domain." : "Stai accedendo al server da un dominio non attendibile.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contatta il tuo amministratore di sistema. Se sei un amministratore di questa istanza, configura l'impostazione \"trusted_domain\" in config/config.php. Un esempio di configurazione è disponibile in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "In base alla tua configurazione, come amministratore potrai utilizzare anche il pulsante in basso per rendere attendibile questo dominio.", "Add \"%s\" as trusted domain" : "Aggiungi \"%s\" come dominio attendibile", "App update required" : "Aggiornamento dell'applicazione richiesto", diff --git a/core/l10n/it.json b/core/l10n/it.json index 63e6e50886b..944a615653a 100644 --- a/core/l10n/it.json +++ b/core/l10n/it.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Contatta il tuo amministratore di sistema se questo messaggio persiste o appare inaspettatamente.", "Thank you for your patience." : "Grazie per la pazienza.", "You are accessing the server from an untrusted domain." : "Stai accedendo al server da un dominio non attendibile.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contatta il tuo amministratore di sistema. Se sei un amministratore di questa istanza, configura l'impostazione \"trusted_domain\" in config/config.php. Un esempio di configurazione è disponibile in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "In base alla tua configurazione, come amministratore potrai utilizzare anche il pulsante in basso per rendere attendibile questo dominio.", "Add \"%s\" as trusted domain" : "Aggiungi \"%s\" come dominio attendibile", "App update required" : "Aggiornamento dell'applicazione richiesto", diff --git a/core/l10n/ja.js b/core/l10n/ja.js index 84c4b1bb0df..c1fef991cc5 100644 --- a/core/l10n/ja.js +++ b/core/l10n/ja.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。", "Thank you for your patience." : "しばらくお待ちください。", "You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。", "Add \"%s\" as trusted domain" : "\"%s\" を信頼するドメイン名に追加", "App update required" : "アプリの更新が必要", diff --git a/core/l10n/ja.json b/core/l10n/ja.json index f8e5ccd4328..99dfb583ccc 100644 --- a/core/l10n/ja.json +++ b/core/l10n/ja.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。", "Thank you for your patience." : "しばらくお待ちください。", "You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。", "Add \"%s\" as trusted domain" : "\"%s\" を信頼するドメイン名に追加", "App update required" : "アプリの更新が必要", diff --git a/core/l10n/ko.js b/core/l10n/ko.js index f2259373023..97c6d5dcdec 100644 --- a/core/l10n/ko.js +++ b/core/l10n/ko.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "이 메시지가 계속 표시되거나, 예상하지 못하였을 때 표시된다면 시스템 관리자에게 연락하십시오", "Thank you for your patience." : "기다려 주셔서 감사합니다.", "You are accessing the server from an untrusted domain." : "신뢰할 수 없는 도메인으로 서버에 접근하고 있습니다.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "관리자에게 연락해 주십시오. 만약 이 인스턴스 관리자라면 config/config.php에서 \"trusted_domain\" 설정을 편집하십시오. 예제 설정 파일은 config/config.sample.php에 있습니다.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "설정에 따라서 관리자 권한으로 아래 단추를 눌러서 이 도메인을 신뢰하도록 설정할 수 있습니다.", "Add \"%s\" as trusted domain" : "\"%s\"을(를) 신뢰할 수 있는 도메인으로 추가", "App update required" : "앱 업데이트 필요", diff --git a/core/l10n/ko.json b/core/l10n/ko.json index 43b09d13f1c..293242a2f62 100644 --- a/core/l10n/ko.json +++ b/core/l10n/ko.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "이 메시지가 계속 표시되거나, 예상하지 못하였을 때 표시된다면 시스템 관리자에게 연락하십시오", "Thank you for your patience." : "기다려 주셔서 감사합니다.", "You are accessing the server from an untrusted domain." : "신뢰할 수 없는 도메인으로 서버에 접근하고 있습니다.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "관리자에게 연락해 주십시오. 만약 이 인스턴스 관리자라면 config/config.php에서 \"trusted_domain\" 설정을 편집하십시오. 예제 설정 파일은 config/config.sample.php에 있습니다.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "설정에 따라서 관리자 권한으로 아래 단추를 눌러서 이 도메인을 신뢰하도록 설정할 수 있습니다.", "Add \"%s\" as trusted domain" : "\"%s\"을(를) 신뢰할 수 있는 도메인으로 추가", "App update required" : "앱 업데이트 필요", diff --git a/core/l10n/nb_NO.js b/core/l10n/nb_NO.js index 2975b6b7c0a..b21e5d6b17c 100644 --- a/core/l10n/nb_NO.js +++ b/core/l10n/nb_NO.js @@ -252,6 +252,7 @@ OC.L10N.register( "Finishing …" : "Ferdigstiller ...", "Need help?" : "Trenger du hjelp?", "See the documentation" : "Se dokumentasjonen", + "Hey there,

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

" : "Hei,

Dette er en beskjed om at %s delte %s med deg.
Vis den!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Denne applikasjonen krever JavaScript for å fungere korrekt. Vennligst {linkstart}aktiver JavaScript{linkend} og last siden på nytt.", "Log out" : "Logg ut", "Search" : "Søk", @@ -263,13 +264,11 @@ OC.L10N.register( "Wrong password. Reset it?" : "Feil passord. Nullstille det?", "Stay logged in" : "Forbli innlogget", "Alternative Logins" : "Alternative innlogginger", - "Hey there,

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

" : "Hei,

Dette er en beskjed om at %s delte %s med deg.
Vis den!

", "This ownCloud instance is currently in single user mode." : "Denne ownCloud-instansen er for øyeblikket i enbrukermodus.", "This means only administrators can use the instance." : "Dette betyr at kun administratorer kan bruke instansen.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakt systemadministratoren hvis denne meldingen var uventet eller ikke forsvinner.", "Thank you for your patience." : "Takk for din tålmodighet.", "You are accessing the server from an untrusted domain." : "Du aksesserer serveren fra et ikke tiltrodd domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Vennligst kontakt administratoren. Hvis du er administrator for denne instansen, konfigurer innstillingen \"trusted_domain\" i config/config.php. En eksempelkonfigurasjon er gitt i config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Avhengig av konfigurasjonen kan du, som administrator, kanskje også bruke kanppen nedenfor til å stole på dette domenet.", "Add \"%s\" as trusted domain" : "Legg til \"%s\" som et tiltrodd domene", "App update required" : "App-oppdatering kreves", diff --git a/core/l10n/nb_NO.json b/core/l10n/nb_NO.json index 5c1d64df3fc..cb67534cd01 100644 --- a/core/l10n/nb_NO.json +++ b/core/l10n/nb_NO.json @@ -250,6 +250,7 @@ "Finishing …" : "Ferdigstiller ...", "Need help?" : "Trenger du hjelp?", "See the documentation" : "Se dokumentasjonen", + "Hey there,

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

" : "Hei,

Dette er en beskjed om at %s delte %s med deg.
Vis den!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Denne applikasjonen krever JavaScript for å fungere korrekt. Vennligst {linkstart}aktiver JavaScript{linkend} og last siden på nytt.", "Log out" : "Logg ut", "Search" : "Søk", @@ -261,13 +262,11 @@ "Wrong password. Reset it?" : "Feil passord. Nullstille det?", "Stay logged in" : "Forbli innlogget", "Alternative Logins" : "Alternative innlogginger", - "Hey there,

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

" : "Hei,

Dette er en beskjed om at %s delte %s med deg.
Vis den!

", "This ownCloud instance is currently in single user mode." : "Denne ownCloud-instansen er for øyeblikket i enbrukermodus.", "This means only administrators can use the instance." : "Dette betyr at kun administratorer kan bruke instansen.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontakt systemadministratoren hvis denne meldingen var uventet eller ikke forsvinner.", "Thank you for your patience." : "Takk for din tålmodighet.", "You are accessing the server from an untrusted domain." : "Du aksesserer serveren fra et ikke tiltrodd domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Vennligst kontakt administratoren. Hvis du er administrator for denne instansen, konfigurer innstillingen \"trusted_domain\" i config/config.php. En eksempelkonfigurasjon er gitt i config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Avhengig av konfigurasjonen kan du, som administrator, kanskje også bruke kanppen nedenfor til å stole på dette domenet.", "Add \"%s\" as trusted domain" : "Legg til \"%s\" som et tiltrodd domene", "App update required" : "App-oppdatering kreves", diff --git a/core/l10n/nl.js b/core/l10n/nl.js index 90dfb6c66a7..f4702077004 100644 --- a/core/l10n/nl.js +++ b/core/l10n/nl.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Neem contact op met uw systeembeheerder als deze melding aanhoudt of onverwacht verscheen.", "Thank you for your patience." : "Bedankt voor uw geduld.", "You are accessing the server from an untrusted domain." : "U benadert de server vanaf een niet vertrouwd domein.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Neem contact op met uw beheerder. Als u de beheerder van deze service bent, configureer dan de \"trusted_domain\" instelling in config/config.php. Een voorbeeldconfiguratie is gegeven in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Afhankelijk van uw configuratie zou u als beheerder ook de onderstaande knop kunnen gebruiken om dit domein te vertrouwen.", "Add \"%s\" as trusted domain" : "\"%s\" toevoegen als vertrouwd domein", "App update required" : "Bijwerken App vereist", diff --git a/core/l10n/nl.json b/core/l10n/nl.json index a65c6f7c001..a86bbe3d4af 100644 --- a/core/l10n/nl.json +++ b/core/l10n/nl.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Neem contact op met uw systeembeheerder als deze melding aanhoudt of onverwacht verscheen.", "Thank you for your patience." : "Bedankt voor uw geduld.", "You are accessing the server from an untrusted domain." : "U benadert de server vanaf een niet vertrouwd domein.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Neem contact op met uw beheerder. Als u de beheerder van deze service bent, configureer dan de \"trusted_domain\" instelling in config/config.php. Een voorbeeldconfiguratie is gegeven in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Afhankelijk van uw configuratie zou u als beheerder ook de onderstaande knop kunnen gebruiken om dit domein te vertrouwen.", "Add \"%s\" as trusted domain" : "\"%s\" toevoegen als vertrouwd domein", "App update required" : "Bijwerken App vereist", diff --git a/core/l10n/oc.js b/core/l10n/oc.js index ae35ffe9951..6c27148b497 100644 --- a/core/l10n/oc.js +++ b/core/l10n/oc.js @@ -252,6 +252,7 @@ OC.L10N.register( "Finishing …" : "Finalizacion …", "Need help?" : "Besonh d'ajuda ?", "See the documentation" : "Legir la documentacion", + "Hey there,

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

" : "Bonjorn,

Vos informam que %s a partejat %s amb vos.
Clicatz aicí per i accedir !

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Aquesta aplicacion requerís JavaScript per foncionar corrèctament. {linkstart}Activatz JavaScript{linkend} e recargatz la pagina.", "Log out" : "Se desconnectar", "Search" : "Recercar", @@ -263,13 +264,11 @@ OC.L10N.register( "Wrong password. Reset it?" : "Senhal incorrècte. Reïnicializar ?", "Stay logged in" : "Demorar connectat", "Alternative Logins" : "Identificants alternatius", - "Hey there,

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

" : "Bonjorn,

Vos informam que %s a partejat %s amb vos.
Clicatz aicí per i accedir !

", "This ownCloud instance is currently in single user mode." : "Aquesta instància de ownCloud es actualament en mòde utilizaire unic.", "This means only administrators can use the instance." : "Aquò significa que sols los administrators pòdon utilizar l'instància.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contactatz vòstre administrator sistèma se aqueste messatge persistís o apareis de faiçon imprevista.", "Thank you for your patience." : "Mercé de vòstra paciéncia.", "You are accessing the server from an untrusted domain." : "Accedissètz al servidor a partir d'un domeni pas aprovat.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contactatz vòstre administrator. Se sètz administrator d'aquesta instància, configuratz lo paramètre « trusted_domain » dins lo fichièr config/config.php. Un exemple de configuracion es provesit dins lo fichièr config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En foncion de vòstra configuracion, en tant qu'administrator podètz tanben utilizar lo boton çaijós per aprovar aqueste domeni.", "Add \"%s\" as trusted domain" : "Apondre \"%s\" a la lista dels domenis aprovats", "App update required" : "Mesa a jorn de l'aplicacion necessària", diff --git a/core/l10n/oc.json b/core/l10n/oc.json index 182747d995c..c73667e6f1c 100644 --- a/core/l10n/oc.json +++ b/core/l10n/oc.json @@ -250,6 +250,7 @@ "Finishing …" : "Finalizacion …", "Need help?" : "Besonh d'ajuda ?", "See the documentation" : "Legir la documentacion", + "Hey there,

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

" : "Bonjorn,

Vos informam que %s a partejat %s amb vos.
Clicatz aicí per i accedir !

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Aquesta aplicacion requerís JavaScript per foncionar corrèctament. {linkstart}Activatz JavaScript{linkend} e recargatz la pagina.", "Log out" : "Se desconnectar", "Search" : "Recercar", @@ -261,13 +262,11 @@ "Wrong password. Reset it?" : "Senhal incorrècte. Reïnicializar ?", "Stay logged in" : "Demorar connectat", "Alternative Logins" : "Identificants alternatius", - "Hey there,

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

" : "Bonjorn,

Vos informam que %s a partejat %s amb vos.
Clicatz aicí per i accedir !

", "This ownCloud instance is currently in single user mode." : "Aquesta instància de ownCloud es actualament en mòde utilizaire unic.", "This means only administrators can use the instance." : "Aquò significa que sols los administrators pòdon utilizar l'instància.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contactatz vòstre administrator sistèma se aqueste messatge persistís o apareis de faiçon imprevista.", "Thank you for your patience." : "Mercé de vòstra paciéncia.", "You are accessing the server from an untrusted domain." : "Accedissètz al servidor a partir d'un domeni pas aprovat.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Contactatz vòstre administrator. Se sètz administrator d'aquesta instància, configuratz lo paramètre « trusted_domain » dins lo fichièr config/config.php. Un exemple de configuracion es provesit dins lo fichièr config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En foncion de vòstra configuracion, en tant qu'administrator podètz tanben utilizar lo boton çaijós per aprovar aqueste domeni.", "Add \"%s\" as trusted domain" : "Apondre \"%s\" a la lista dels domenis aprovats", "App update required" : "Mesa a jorn de l'aplicacion necessària", diff --git a/core/l10n/pl.js b/core/l10n/pl.js index 9f27338611d..972506283e9 100644 --- a/core/l10n/pl.js +++ b/core/l10n/pl.js @@ -198,6 +198,7 @@ OC.L10N.register( "Finish setup" : "Zakończ konfigurowanie", "Finishing …" : "Kończę ...", "Need help?" : "Potrzebujesz pomocy?", + "Hey there,

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

" : "Witam,

informuję, że %s udostępnianych zasobów %s jest z Tobą.
Zobacz!

", "Log out" : "Wyloguj", "Search" : "Wyszukaj", "Server side authentication failed!" : "Uwierzytelnianie po stronie serwera nie powiodło się!", @@ -205,13 +206,11 @@ OC.L10N.register( "Please try again or contact your administrator." : "Spróbuj ponownie lub skontaktuj się z administratorem.", "Log in" : "Zaloguj", "Alternative Logins" : "Alternatywne loginy", - "Hey there,

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

" : "Witam,

informuję, że %s udostępnianych zasobów %s jest z Tobą.
Zobacz!

", "This ownCloud instance is currently in single user mode." : "Ta instalacja ownCloud działa obecnie w trybie pojedynczego użytkownika.", "This means only administrators can use the instance." : "To oznacza, że tylko administratorzy mogą w tej chwili używać aplikacji.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Skontaktuj się z administratorem, jeśli ten komunikat pojawił się nieoczekiwanie lub wyświetla się ciągle.", "Thank you for your patience." : "Dziękuję za cierpliwość.", "You are accessing the server from an untrusted domain." : "Dostajesz się do serwera z niezaufanej domeny.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Proszę skontaktuj się z administratorem. Jeśli jesteś administratorem tej instancji, skonfiguruj parametr \"trusted_domain\" w pliku config/config.php. Przykładowa konfiguracja jest dostępna w pliku config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "W zależności od konfiguracji, jako administrator możesz także użyć poniższego przycisku aby zaufać tej domenie.", "Add \"%s\" as trusted domain" : "Dodaj \"%s\" jako domenę zaufaną", "The theme %s has been disabled." : "Motyw %s został wyłączony.", diff --git a/core/l10n/pl.json b/core/l10n/pl.json index f7f0db1ee09..05c38bdcc0f 100644 --- a/core/l10n/pl.json +++ b/core/l10n/pl.json @@ -196,6 +196,7 @@ "Finish setup" : "Zakończ konfigurowanie", "Finishing …" : "Kończę ...", "Need help?" : "Potrzebujesz pomocy?", + "Hey there,

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

" : "Witam,

informuję, że %s udostępnianych zasobów %s jest z Tobą.
Zobacz!

", "Log out" : "Wyloguj", "Search" : "Wyszukaj", "Server side authentication failed!" : "Uwierzytelnianie po stronie serwera nie powiodło się!", @@ -203,13 +204,11 @@ "Please try again or contact your administrator." : "Spróbuj ponownie lub skontaktuj się z administratorem.", "Log in" : "Zaloguj", "Alternative Logins" : "Alternatywne loginy", - "Hey there,

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

" : "Witam,

informuję, że %s udostępnianych zasobów %s jest z Tobą.
Zobacz!

", "This ownCloud instance is currently in single user mode." : "Ta instalacja ownCloud działa obecnie w trybie pojedynczego użytkownika.", "This means only administrators can use the instance." : "To oznacza, że tylko administratorzy mogą w tej chwili używać aplikacji.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Skontaktuj się z administratorem, jeśli ten komunikat pojawił się nieoczekiwanie lub wyświetla się ciągle.", "Thank you for your patience." : "Dziękuję za cierpliwość.", "You are accessing the server from an untrusted domain." : "Dostajesz się do serwera z niezaufanej domeny.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Proszę skontaktuj się z administratorem. Jeśli jesteś administratorem tej instancji, skonfiguruj parametr \"trusted_domain\" w pliku config/config.php. Przykładowa konfiguracja jest dostępna w pliku config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "W zależności od konfiguracji, jako administrator możesz także użyć poniższego przycisku aby zaufać tej domenie.", "Add \"%s\" as trusted domain" : "Dodaj \"%s\" jako domenę zaufaną", "The theme %s has been disabled." : "Motyw %s został wyłączony.", diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index ea4c0a46210..44850a9f00b 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -252,6 +252,7 @@ OC.L10N.register( "Finishing …" : "Finalizando ...", "Need help?" : "Precisa de ajuda?", "See the documentation" : "Veja a documentação", + "Hey there,

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

" : "Olá,

só para seu conhecimento que %s compartilhou %s com você.
Verificar!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Esta aplicação requer JavaScript para sua correta operação. Por favor {linkstart}habilite JavaScript{linkend} e recerregue a página.", "Log out" : "Sair", "Search" : "Perquisar", @@ -263,13 +264,11 @@ OC.L10N.register( "Wrong password. Reset it?" : "Senha incorreta. Redefini-la?", "Stay logged in" : "Permaneça logado", "Alternative Logins" : "Logins Alternativos", - "Hey there,

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

" : "Olá,

só para seu conhecimento que %s compartilhou %s com você.
Verificar!

", "This ownCloud instance is currently in single user mode." : "Nesta instância ownCloud está em modo de usuário único.", "This means only administrators can use the instance." : "Isso significa que apenas os administradores podem usar esta instância.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte o seu administrador do sistema se esta mensagem persistir ou aparecer inesperadamente.", "Thank you for your patience." : "Obrigado pela sua paciência.", "You are accessing the server from an untrusted domain." : "Você está acessando o servidor a partir de um domínio não confiável.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor, contate o administrador. Se você é um administrador desta instância, configurre o \"trusted_domain\" em config/config.php. Um exemplo de configuração é fornecido em config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da configuração, como administrador, você também pode ser capaz de usar o botão abaixo para confiar neste domínio.", "Add \"%s\" as trusted domain" : "Adicionar \"%s\" como um domínio confiavel", "App update required" : "Atualização de aplicativo é requerida", diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 1b9c9d7e8b0..20300cf2343 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -250,6 +250,7 @@ "Finishing …" : "Finalizando ...", "Need help?" : "Precisa de ajuda?", "See the documentation" : "Veja a documentação", + "Hey there,

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

" : "Olá,

só para seu conhecimento que %s compartilhou %s com você.
Verificar!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Esta aplicação requer JavaScript para sua correta operação. Por favor {linkstart}habilite JavaScript{linkend} e recerregue a página.", "Log out" : "Sair", "Search" : "Perquisar", @@ -261,13 +262,11 @@ "Wrong password. Reset it?" : "Senha incorreta. Redefini-la?", "Stay logged in" : "Permaneça logado", "Alternative Logins" : "Logins Alternativos", - "Hey there,

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

" : "Olá,

só para seu conhecimento que %s compartilhou %s com você.
Verificar!

", "This ownCloud instance is currently in single user mode." : "Nesta instância ownCloud está em modo de usuário único.", "This means only administrators can use the instance." : "Isso significa que apenas os administradores podem usar esta instância.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte o seu administrador do sistema se esta mensagem persistir ou aparecer inesperadamente.", "Thank you for your patience." : "Obrigado pela sua paciência.", "You are accessing the server from an untrusted domain." : "Você está acessando o servidor a partir de um domínio não confiável.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor, contate o administrador. Se você é um administrador desta instância, configurre o \"trusted_domain\" em config/config.php. Um exemplo de configuração é fornecido em config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da configuração, como administrador, você também pode ser capaz de usar o botão abaixo para confiar neste domínio.", "Add \"%s\" as trusted domain" : "Adicionar \"%s\" como um domínio confiavel", "App update required" : "Atualização de aplicativo é requerida", diff --git a/core/l10n/pt_PT.js b/core/l10n/pt_PT.js index e00f09e7eff..53b9ab0bf77 100644 --- a/core/l10n/pt_PT.js +++ b/core/l10n/pt_PT.js @@ -260,7 +260,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte o seu administrador de sistema se esta mensagem continuar a aparecer ou apareceu inesperadamente.", "Thank you for your patience." : "Obrigado pela sua paciência.", "You are accessing the server from an untrusted domain." : "Está a aceder ao servidor a partir de um domínio que não é de confiança.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor contacte o seu administrador. Se é um administrador desta instância, configure as definições \"trusted_domain\" em config/config.php. Um exemplo de configuração é fornecido em config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da configuração, como administrador, você também pode ser capaz de usar o botão abaixo para confiar neste domínio.", "Add \"%s\" as trusted domain" : "Adicionar \"%s\" como um domínio de confiança", "App update required" : "É necessário atualizar a app", diff --git a/core/l10n/pt_PT.json b/core/l10n/pt_PT.json index b0bf92a78c8..8b7d483f270 100644 --- a/core/l10n/pt_PT.json +++ b/core/l10n/pt_PT.json @@ -258,7 +258,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte o seu administrador de sistema se esta mensagem continuar a aparecer ou apareceu inesperadamente.", "Thank you for your patience." : "Obrigado pela sua paciência.", "You are accessing the server from an untrusted domain." : "Está a aceder ao servidor a partir de um domínio que não é de confiança.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Por favor contacte o seu administrador. Se é um administrador desta instância, configure as definições \"trusted_domain\" em config/config.php. Um exemplo de configuração é fornecido em config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da configuração, como administrador, você também pode ser capaz de usar o botão abaixo para confiar neste domínio.", "Add \"%s\" as trusted domain" : "Adicionar \"%s\" como um domínio de confiança", "App update required" : "É necessário atualizar a app", diff --git a/core/l10n/ru.js b/core/l10n/ru.js index 46af1eb6a56..2df910a6aa4 100644 --- a/core/l10n/ru.js +++ b/core/l10n/ru.js @@ -251,6 +251,7 @@ OC.L10N.register( "Finishing …" : "Завершение...", "Need help?" : "Нужна помощь?", "See the documentation" : "Посмотреть документацию", + "Hey there,

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

" : "Здравствуйте,

%s поделился с вами %s.
Перейдите по ссылке, чтобы посмотреть

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Это приложение требует включённый JavaScript для корректной работы. Пожалуйста, включите JavaScript и перезагрузите интерфейс.", "Log out" : "Выйти", "Search" : "Найти", @@ -262,13 +263,11 @@ OC.L10N.register( "Wrong password. Reset it?" : "Неправильный пароль. Сбросить его?", "Stay logged in" : "Оставаться в системе", "Alternative Logins" : "Альтернативные имена пользователя", - "Hey there,

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

" : "Здравствуйте,

%s поделился с вами %s.
Перейдите по ссылке, чтобы посмотреть

", "This ownCloud instance is currently in single user mode." : "Сервер ownCloud в настоящее время работает в однопользовательском режиме.", "This means only administrators can use the instance." : "Это значит, что только администраторы могут использовать сервер.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.", "Thank you for your patience." : "Спасибо за терпение.", "You are accessing the server from an untrusted domain." : "Вы пытаетесь получить доступ к серверу с неподтверждённого домена.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Пожалуйста, свяжитесь с вашим администратором. Если вы администратор этого сервера, сконфигурируйте \"trusted_domain\" в config/config.php. Пример настройки можно найти в /config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимости от конфигурации, как администратор вы можете также внести домен в доверенные с помощью кнопки ниже.", "Add \"%s\" as trusted domain" : "Добавить \"%s\" как доверенный домен", "App update required" : "Требуется обновление приложения", diff --git a/core/l10n/ru.json b/core/l10n/ru.json index 07e7a6ba715..66d3b463899 100644 --- a/core/l10n/ru.json +++ b/core/l10n/ru.json @@ -249,6 +249,7 @@ "Finishing …" : "Завершение...", "Need help?" : "Нужна помощь?", "See the documentation" : "Посмотреть документацию", + "Hey there,

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

" : "Здравствуйте,

%s поделился с вами %s.
Перейдите по ссылке, чтобы посмотреть

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Это приложение требует включённый JavaScript для корректной работы. Пожалуйста, включите JavaScript и перезагрузите интерфейс.", "Log out" : "Выйти", "Search" : "Найти", @@ -260,13 +261,11 @@ "Wrong password. Reset it?" : "Неправильный пароль. Сбросить его?", "Stay logged in" : "Оставаться в системе", "Alternative Logins" : "Альтернативные имена пользователя", - "Hey there,

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

" : "Здравствуйте,

%s поделился с вами %s.
Перейдите по ссылке, чтобы посмотреть

", "This ownCloud instance is currently in single user mode." : "Сервер ownCloud в настоящее время работает в однопользовательском режиме.", "This means only administrators can use the instance." : "Это значит, что только администраторы могут использовать сервер.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.", "Thank you for your patience." : "Спасибо за терпение.", "You are accessing the server from an untrusted domain." : "Вы пытаетесь получить доступ к серверу с неподтверждённого домена.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Пожалуйста, свяжитесь с вашим администратором. Если вы администратор этого сервера, сконфигурируйте \"trusted_domain\" в config/config.php. Пример настройки можно найти в /config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимости от конфигурации, как администратор вы можете также внести домен в доверенные с помощью кнопки ниже.", "Add \"%s\" as trusted domain" : "Добавить \"%s\" как доверенный домен", "App update required" : "Требуется обновление приложения", diff --git a/core/l10n/sk_SK.js b/core/l10n/sk_SK.js index 97114cd1ceb..2968a570a25 100644 --- a/core/l10n/sk_SK.js +++ b/core/l10n/sk_SK.js @@ -262,7 +262,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktujte prosím správcu systému, ak sa táto správa objavuje opakovane alebo neočakávane.", "Thank you for your patience." : "Ďakujeme za Vašu trpezlivosť.", "You are accessing the server from an untrusted domain." : "Pristupujete na server v nedôveryhodnej doméne.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kontaktujte správcu. Ak ste správcom tejto inštancie, nakonfigurujte správne nastavenie \"trusted_domain\" v config/config.php. Vzorová konfigurácia je uvedená v config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "V závislosti na konfigurácii, vám môže byť ako správcovi umožnené použitie tlačidla nižšie pre označenie tejto domény ako dôveryhodnej.", "Add \"%s\" as trusted domain" : "Pridať \"%s\" ako dôveryhodnú doménu", "App update required" : "Je nutná aktualizácia aplikácie", diff --git a/core/l10n/sk_SK.json b/core/l10n/sk_SK.json index 9aac003a3ba..537985d28ed 100644 --- a/core/l10n/sk_SK.json +++ b/core/l10n/sk_SK.json @@ -260,7 +260,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktujte prosím správcu systému, ak sa táto správa objavuje opakovane alebo neočakávane.", "Thank you for your patience." : "Ďakujeme za Vašu trpezlivosť.", "You are accessing the server from an untrusted domain." : "Pristupujete na server v nedôveryhodnej doméne.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Kontaktujte správcu. Ak ste správcom tejto inštancie, nakonfigurujte správne nastavenie \"trusted_domain\" v config/config.php. Vzorová konfigurácia je uvedená v config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "V závislosti na konfigurácii, vám môže byť ako správcovi umožnené použitie tlačidla nižšie pre označenie tejto domény ako dôveryhodnej.", "Add \"%s\" as trusted domain" : "Pridať \"%s\" ako dôveryhodnú doménu", "App update required" : "Je nutná aktualizácia aplikácie", diff --git a/core/l10n/sl.js b/core/l10n/sl.js index fdc815cef43..3398a9bd2ee 100644 --- a/core/l10n/sl.js +++ b/core/l10n/sl.js @@ -193,19 +193,18 @@ OC.L10N.register( "SQLite will be used as database." : "Kot podatkovna zbirka bo uporabljena zbirka SQLite", "Finish setup" : "Končaj nastavitev", "Finishing …" : "Poteka zaključevanje opravila ...", + "Hey there,

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

" : "Pozdravljeni,

uporabnik %s vam je omogočil souporabo %s.
Oglejte si vsebino!

", "Log out" : "Odjava", "Search" : "Poišči", "Server side authentication failed!" : "Overitev s strežnika je spodletela!", "Please contact your administrator." : "Stopite v stik s skrbnikom sistema.", "Log in" : "Prijava", "Alternative Logins" : "Druge prijavne možnosti", - "Hey there,

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

" : "Pozdravljeni,

uporabnik %s vam je omogočil souporabo %s.
Oglejte si vsebino!

", "This ownCloud instance is currently in single user mode." : "Ta seja oblaka ownCloud je trenutno v načinu enega sočasnega uporabnika.", "This means only administrators can use the instance." : "To pomeni, da lahko oblak uporabljajo le osebe s skrbniškimi dovoljenji.", "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!", "You are accessing the server from an untrusted domain." : "Trenutno je vzpostavljena povezava s strežnikom preko ne-varne domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Stopite v stik s skrbnikom ali pa nastavite možnost \"varna_domena\" v datoteki config/config.php. Primer nastavitve je razložen v datoteki config/config.sample.php.", "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", "The theme %s has been disabled." : "Tema %s je onemogočena za uporabo.", diff --git a/core/l10n/sl.json b/core/l10n/sl.json index 97bf940222e..866a6dca670 100644 --- a/core/l10n/sl.json +++ b/core/l10n/sl.json @@ -191,19 +191,18 @@ "SQLite will be used as database." : "Kot podatkovna zbirka bo uporabljena zbirka SQLite", "Finish setup" : "Končaj nastavitev", "Finishing …" : "Poteka zaključevanje opravila ...", + "Hey there,

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

" : "Pozdravljeni,

uporabnik %s vam je omogočil souporabo %s.
Oglejte si vsebino!

", "Log out" : "Odjava", "Search" : "Poišči", "Server side authentication failed!" : "Overitev s strežnika je spodletela!", "Please contact your administrator." : "Stopite v stik s skrbnikom sistema.", "Log in" : "Prijava", "Alternative Logins" : "Druge prijavne možnosti", - "Hey there,

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

" : "Pozdravljeni,

uporabnik %s vam je omogočil souporabo %s.
Oglejte si vsebino!

", "This ownCloud instance is currently in single user mode." : "Ta seja oblaka ownCloud je trenutno v načinu enega sočasnega uporabnika.", "This means only administrators can use the instance." : "To pomeni, da lahko oblak uporabljajo le osebe s skrbniškimi dovoljenji.", "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!", "You are accessing the server from an untrusted domain." : "Trenutno je vzpostavljena povezava s strežnikom preko ne-varne domene.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Stopite v stik s skrbnikom ali pa nastavite možnost \"varna_domena\" v datoteki config/config.php. Primer nastavitve je razložen v datoteki config/config.sample.php.", "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", "The theme %s has been disabled." : "Tema %s je onemogočena za uporabo.", diff --git a/core/l10n/sq.js b/core/l10n/sq.js index 8580832837c..7a3ba05abef 100644 --- a/core/l10n/sq.js +++ b/core/l10n/sq.js @@ -252,6 +252,7 @@ OC.L10N.register( "Finishing …" : "Po përfundohet …", "Need help?" : "Ju duhet ndihmë?", "See the documentation" : "Shihni dokumentimin", + "Hey there,

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

" : "Njatjeta,

thjesht po ju bëjmë të ditur që %s ndau me ju %s.
Shiheni!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ky aplikacion lyp JavaScript për punim të saktë. Ju lutemi, {linkstart}aktivizoni JavaScript-in{linkend} dhe ringarkoni faqen.", "Log out" : "Dilni", "Search" : "Kërko", @@ -263,13 +264,11 @@ OC.L10N.register( "Wrong password. Reset it?" : "Fjalëkalim i gabuar. Të ricaktohet?", "Stay logged in" : "Qëndro i futur", "Alternative Logins" : "Hyrje Alternative", - "Hey there,

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

" : "Njatjeta,

thjesht po ju bëjmë të ditur që %s ndau me ju %s.
Shiheni!

", "This ownCloud instance is currently in single user mode." : "Kjo instancë ownCloud është aktualisht në gjendje me përdorues të vetëm.", "This means only administrators can use the instance." : "Kjo do të thotë që instancën mund ta përdorin vetëm administratorët.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Nëse ky mesazh shfaqet vazhdimisht ose u shfaq papritmas, lidhuni me përgjegjësin e sistemit.", "Thank you for your patience." : "Ju faleminderit për durimin.", "You are accessing the server from an untrusted domain." : "Po hyni në shërbyes nga një përkatësi jo e besuar.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Ju lutemi, lidhuni me përgjegjësin tuaj. Nëse jeni një përgjegjës në këtë instancë, formësoni rregullimin \"trusted_domain\" te config/config.php. Një formësim shembull jepet te config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Në varësi të formësimit tuaj, si administrator mundet gjithashtu të jeni në gjendje të përdorni butonin më poshtë për ta besuar këtë përkatësi.", "Add \"%s\" as trusted domain" : "Shtojeni \"%s\" si përkatësi të besuar", "App update required" : "Lypset përditësim aplikacioni", diff --git a/core/l10n/sq.json b/core/l10n/sq.json index 0e2257d35e6..057510bfe94 100644 --- a/core/l10n/sq.json +++ b/core/l10n/sq.json @@ -250,6 +250,7 @@ "Finishing …" : "Po përfundohet …", "Need help?" : "Ju duhet ndihmë?", "See the documentation" : "Shihni dokumentimin", + "Hey there,

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

" : "Njatjeta,

thjesht po ju bëjmë të ditur që %s ndau me ju %s.
Shiheni!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ky aplikacion lyp JavaScript për punim të saktë. Ju lutemi, {linkstart}aktivizoni JavaScript-in{linkend} dhe ringarkoni faqen.", "Log out" : "Dilni", "Search" : "Kërko", @@ -261,13 +262,11 @@ "Wrong password. Reset it?" : "Fjalëkalim i gabuar. Të ricaktohet?", "Stay logged in" : "Qëndro i futur", "Alternative Logins" : "Hyrje Alternative", - "Hey there,

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

" : "Njatjeta,

thjesht po ju bëjmë të ditur që %s ndau me ju %s.
Shiheni!

", "This ownCloud instance is currently in single user mode." : "Kjo instancë ownCloud është aktualisht në gjendje me përdorues të vetëm.", "This means only administrators can use the instance." : "Kjo do të thotë që instancën mund ta përdorin vetëm administratorët.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Nëse ky mesazh shfaqet vazhdimisht ose u shfaq papritmas, lidhuni me përgjegjësin e sistemit.", "Thank you for your patience." : "Ju faleminderit për durimin.", "You are accessing the server from an untrusted domain." : "Po hyni në shërbyes nga një përkatësi jo e besuar.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Ju lutemi, lidhuni me përgjegjësin tuaj. Nëse jeni një përgjegjës në këtë instancë, formësoni rregullimin \"trusted_domain\" te config/config.php. Një formësim shembull jepet te config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Në varësi të formësimit tuaj, si administrator mundet gjithashtu të jeni në gjendje të përdorni butonin më poshtë për ta besuar këtë përkatësi.", "Add \"%s\" as trusted domain" : "Shtojeni \"%s\" si përkatësi të besuar", "App update required" : "Lypset përditësim aplikacioni", diff --git a/core/l10n/sr.js b/core/l10n/sr.js index 8471c00b131..aac106e61ad 100644 --- a/core/l10n/sr.js +++ b/core/l10n/sr.js @@ -230,6 +230,7 @@ OC.L10N.register( "Finishing …" : "Завршавам…", "Need help?" : "Треба вам помоћ?", "See the documentation" : "Погледајте документацију", + "Hey there,

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

" : "Поздрав,

само вас обавештавам да %s дели %s са вама.
Погледајте!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ова апликација захтева Јава скрипт за исправан рад. {linkstart}Омогућите Јава скрипт{linkend} и поново учитајте страницу.", "Log out" : "Одјава", "Search" : "Претражи", @@ -239,13 +240,11 @@ OC.L10N.register( "Please try again or contact your administrator." : "Покушајте поново или контактирајте вашег администратора.", "Log in" : "Пријава", "Alternative Logins" : "Алтернативне пријаве", - "Hey there,

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

" : "Поздрав,

само вас обавештавам да %s дели %s са вама.
Погледајте!

", "This ownCloud instance is currently in single user mode." : "Овај оунКлауд тренутно ради у режиму једног корисника.", "This means only administrators can use the instance." : "То значи да га могу користити само администратори.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Контактирајте администратора ако се порука понавља или се неочекивано појавила.", "Thank you for your patience." : "Хвала вам на стрпљењу.", "You are accessing the server from an untrusted domain." : "Приступате серверу са непоузданог домена.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Контактирајте администратора. Ако сте ви администратор, подесите „trusted_domain“ поставку у config/config.php фајлу. Пример подешавања имате у config/config.sample.php фајлу.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Зависно од ваших подешавања, као администратор можете употребити дугме испод да потврдите поузданост домена.", "Add \"%s\" as trusted domain" : "Додај „%s“ као поуздан домен", "The theme %s has been disabled." : "Тема %s је онемогућена.", diff --git a/core/l10n/sr.json b/core/l10n/sr.json index 2f02b8acd33..c3af2764d0b 100644 --- a/core/l10n/sr.json +++ b/core/l10n/sr.json @@ -228,6 +228,7 @@ "Finishing …" : "Завршавам…", "Need help?" : "Треба вам помоћ?", "See the documentation" : "Погледајте документацију", + "Hey there,

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

" : "Поздрав,

само вас обавештавам да %s дели %s са вама.
Погледајте!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ова апликација захтева Јава скрипт за исправан рад. {linkstart}Омогућите Јава скрипт{linkend} и поново учитајте страницу.", "Log out" : "Одјава", "Search" : "Претражи", @@ -237,13 +238,11 @@ "Please try again or contact your administrator." : "Покушајте поново или контактирајте вашег администратора.", "Log in" : "Пријава", "Alternative Logins" : "Алтернативне пријаве", - "Hey there,

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

" : "Поздрав,

само вас обавештавам да %s дели %s са вама.
Погледајте!

", "This ownCloud instance is currently in single user mode." : "Овај оунКлауд тренутно ради у режиму једног корисника.", "This means only administrators can use the instance." : "То значи да га могу користити само администратори.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Контактирајте администратора ако се порука понавља или се неочекивано појавила.", "Thank you for your patience." : "Хвала вам на стрпљењу.", "You are accessing the server from an untrusted domain." : "Приступате серверу са непоузданог домена.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Контактирајте администратора. Ако сте ви администратор, подесите „trusted_domain“ поставку у config/config.php фајлу. Пример подешавања имате у config/config.sample.php фајлу.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Зависно од ваших подешавања, као администратор можете употребити дугме испод да потврдите поузданост домена.", "Add \"%s\" as trusted domain" : "Додај „%s“ као поуздан домен", "The theme %s has been disabled." : "Тема %s је онемогућена.", diff --git a/core/l10n/sr@latin.js b/core/l10n/sr@latin.js index ea954f3e3ea..18ab8513417 100644 --- a/core/l10n/sr@latin.js +++ b/core/l10n/sr@latin.js @@ -190,19 +190,18 @@ OC.L10N.register( "Database host" : "Domaćin baze", "Finish setup" : "Završi podešavanje", "Finishing …" : "Završavam ...", + "Hey there,

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

" : "Hej,

samo ti javljamo da je %s delio %s sa tobom.
Pogledaj!

", "Log out" : "Odjava", "Search" : "Traži", "Server side authentication failed!" : "Provera identiteta na stani servera nije uspela!", "Please contact your administrator." : "Molimo Vas da kontaktirate Vašeg administratora.", "Log in" : "Prijavi se", "Alternative Logins" : "Alternativne prijave", - "Hey there,

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

" : "Hej,

samo ti javljamo da je %s delio %s sa tobom.
Pogledaj!

", "This ownCloud instance is currently in single user mode." : "Ova instanca ownCloud-a je trenutno u režimu rada jednog korisnika.", "This means only administrators can use the instance." : "Ovo znači da samo administratori mogu da koriste ovu instancu.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte Vašeg sistem administratora ako se ova poruka često ili iznenada pojavljuje.", "Thank you for your patience." : "Hvala Vam na strpljenju.", "You are accessing the server from an untrusted domain." : "Pristupate serveru sa nepouzdanog domena.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molimo Vas da kontaktirate Vašeg administratora. Ako ste Vi administrator ove instance, podesite \"trusted_domain\" podešavanje u config/config.php. Primer podešavanja je dat u config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "U zavisnosti od Vaše konfiguracije, kao administrator bi ste mogli da upotrebite dugme ispod da podesite da verujete ovom domenu.", "Add \"%s\" as trusted domain" : "Dodaj \"%s\" kao domen od poverenja", "The theme %s has been disabled." : "Tema %s će biti onemogućena.", diff --git a/core/l10n/sr@latin.json b/core/l10n/sr@latin.json index 7cd0e7d9408..47b017d5a16 100644 --- a/core/l10n/sr@latin.json +++ b/core/l10n/sr@latin.json @@ -188,19 +188,18 @@ "Database host" : "Domaćin baze", "Finish setup" : "Završi podešavanje", "Finishing …" : "Završavam ...", + "Hey there,

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

" : "Hej,

samo ti javljamo da je %s delio %s sa tobom.
Pogledaj!

", "Log out" : "Odjava", "Search" : "Traži", "Server side authentication failed!" : "Provera identiteta na stani servera nije uspela!", "Please contact your administrator." : "Molimo Vas da kontaktirate Vašeg administratora.", "Log in" : "Prijavi se", "Alternative Logins" : "Alternativne prijave", - "Hey there,

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

" : "Hej,

samo ti javljamo da je %s delio %s sa tobom.
Pogledaj!

", "This ownCloud instance is currently in single user mode." : "Ova instanca ownCloud-a je trenutno u režimu rada jednog korisnika.", "This means only administrators can use the instance." : "Ovo znači da samo administratori mogu da koriste ovu instancu.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte Vašeg sistem administratora ako se ova poruka često ili iznenada pojavljuje.", "Thank you for your patience." : "Hvala Vam na strpljenju.", "You are accessing the server from an untrusted domain." : "Pristupate serveru sa nepouzdanog domena.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molimo Vas da kontaktirate Vašeg administratora. Ako ste Vi administrator ove instance, podesite \"trusted_domain\" podešavanje u config/config.php. Primer podešavanja je dat u config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "U zavisnosti od Vaše konfiguracije, kao administrator bi ste mogli da upotrebite dugme ispod da podesite da verujete ovom domenu.", "Add \"%s\" as trusted domain" : "Dodaj \"%s\" kao domen od poverenja", "The theme %s has been disabled." : "Tema %s će biti onemogućena.", diff --git a/core/l10n/sv.js b/core/l10n/sv.js index 4f00fc52a5b..cde3ece247a 100644 --- a/core/l10n/sv.js +++ b/core/l10n/sv.js @@ -198,19 +198,18 @@ OC.L10N.register( "Finishing …" : "Avslutar ...", "Need help?" : "Behöver du hjälp?", "See the documentation" : "Kolla dokumentationen", + "Hey there,

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

" : "Hej där,

ville bara informera dig om att %s delade %s med dig.
Visa den!

", "Log out" : "Logga ut", "Search" : "Sök", "Server side authentication failed!" : "Servern misslyckades med autentisering!", "Please contact your administrator." : "Kontakta din administratör.", "Log in" : "Logga in", "Alternative Logins" : "Alternativa inloggningar", - "Hey there,

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

" : "Hej där,

ville bara informera dig om att %s delade %s med dig.
Visa den!

", "This ownCloud instance is currently in single user mode." : "Denna ownCloud instans är för närvarande i enanvändarläge", "This means only administrators can use the instance." : "Detta betyder att endast administartörer kan använda instansen.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Hör av dig till din system administratör ifall detta meddelande fortsätter eller visas oväntat.", "Thank you for your patience." : "Tack för ditt tålamod.", "You are accessing the server from an untrusted domain." : "Du ansluter till servern från en osäker domän.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Vänligen kontakta din administratör. Om du är en administratör, konfigurera inställningen \"trusted_domain\" i config/config.php. En exempelkonfiguration finns i tillgänglig i config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Beroende på din konfiguartion, så finns det möjlighet att du som administratör kan använda knappen nedan för att verifiera på denna domän.", "Add \"%s\" as trusted domain" : "Lägg till \"%s\" som en trusted domain", "The theme %s has been disabled." : "Temat %s har blivit inaktiverat.", diff --git a/core/l10n/sv.json b/core/l10n/sv.json index 69113de80bc..5c0666c2011 100644 --- a/core/l10n/sv.json +++ b/core/l10n/sv.json @@ -196,19 +196,18 @@ "Finishing …" : "Avslutar ...", "Need help?" : "Behöver du hjälp?", "See the documentation" : "Kolla dokumentationen", + "Hey there,

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

" : "Hej där,

ville bara informera dig om att %s delade %s med dig.
Visa den!

", "Log out" : "Logga ut", "Search" : "Sök", "Server side authentication failed!" : "Servern misslyckades med autentisering!", "Please contact your administrator." : "Kontakta din administratör.", "Log in" : "Logga in", "Alternative Logins" : "Alternativa inloggningar", - "Hey there,

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

" : "Hej där,

ville bara informera dig om att %s delade %s med dig.
Visa den!

", "This ownCloud instance is currently in single user mode." : "Denna ownCloud instans är för närvarande i enanvändarläge", "This means only administrators can use the instance." : "Detta betyder att endast administartörer kan använda instansen.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Hör av dig till din system administratör ifall detta meddelande fortsätter eller visas oväntat.", "Thank you for your patience." : "Tack för ditt tålamod.", "You are accessing the server from an untrusted domain." : "Du ansluter till servern från en osäker domän.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Vänligen kontakta din administratör. Om du är en administratör, konfigurera inställningen \"trusted_domain\" i config/config.php. En exempelkonfiguration finns i tillgänglig i config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Beroende på din konfiguartion, så finns det möjlighet att du som administratör kan använda knappen nedan för att verifiera på denna domän.", "Add \"%s\" as trusted domain" : "Lägg till \"%s\" som en trusted domain", "The theme %s has been disabled." : "Temat %s har blivit inaktiverat.", diff --git a/core/l10n/th_TH.js b/core/l10n/th_TH.js index 90e774b15bd..fed963670ad 100644 --- a/core/l10n/th_TH.js +++ b/core/l10n/th_TH.js @@ -269,7 +269,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "ติดต่อผู้ดูแลระบบของคุณหากข้อความนี้ยังคงมีอยู่หรือปรากฏโดยไม่คาดคิด", "Thank you for your patience." : "ขอบคุณสำหรับความอดทนของคุณ เราจะนำความคิดเห็นของท่านมาปรับปรุงระบบให้ดียิ่งขึ้น", "You are accessing the server from an untrusted domain." : "คุณกำลังเข้าถึงเซิร์ฟเวอร์จากโดเมนที่ไม่น่าเชื่อถือ", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "กรุณาติดต่อผู้ดูแลระบบ หากคุณเป็นผู้ดูแลระบบโปรดกำหนดค่า \"trusted_domain\" โดยตั้งค่าใน config/config.php ยกตัวอย่างระบุการตั้งค่าใน config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "ทั้งนี้ขึ้นอยู่กับการกำหนดค่าของคุณ ผู้ดูแลระบบอาจสามารถใช้ปุ่มด้านล่างเพื่อกำหนดให้โดเมนนี้มีความน่าเชื่อถือ", "Add \"%s\" as trusted domain" : "ได้เพิ่ม \"%s\" เป็นโดเมนที่เชื่อถือ", "App update required" : "จำเป้นต้องอัพเดทแอพฯ", diff --git a/core/l10n/th_TH.json b/core/l10n/th_TH.json index 80c6b44078c..70c774d4a9d 100644 --- a/core/l10n/th_TH.json +++ b/core/l10n/th_TH.json @@ -267,7 +267,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "ติดต่อผู้ดูแลระบบของคุณหากข้อความนี้ยังคงมีอยู่หรือปรากฏโดยไม่คาดคิด", "Thank you for your patience." : "ขอบคุณสำหรับความอดทนของคุณ เราจะนำความคิดเห็นของท่านมาปรับปรุงระบบให้ดียิ่งขึ้น", "You are accessing the server from an untrusted domain." : "คุณกำลังเข้าถึงเซิร์ฟเวอร์จากโดเมนที่ไม่น่าเชื่อถือ", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "กรุณาติดต่อผู้ดูแลระบบ หากคุณเป็นผู้ดูแลระบบโปรดกำหนดค่า \"trusted_domain\" โดยตั้งค่าใน config/config.php ยกตัวอย่างระบุการตั้งค่าใน config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "ทั้งนี้ขึ้นอยู่กับการกำหนดค่าของคุณ ผู้ดูแลระบบอาจสามารถใช้ปุ่มด้านล่างเพื่อกำหนดให้โดเมนนี้มีความน่าเชื่อถือ", "Add \"%s\" as trusted domain" : "ได้เพิ่ม \"%s\" เป็นโดเมนที่เชื่อถือ", "App update required" : "จำเป้นต้องอัพเดทแอพฯ", diff --git a/core/l10n/tr.js b/core/l10n/tr.js index deb40f27cb5..257550ecd4b 100644 --- a/core/l10n/tr.js +++ b/core/l10n/tr.js @@ -262,7 +262,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Eğer bu ileti görünmeye devam ederse veya beklenmedik şekilde ortaya çıkmışsa sistem yöneticinizle iletişime geçin.", "Thank you for your patience." : "Sabrınız için teşekkür ederiz.", "You are accessing the server from an untrusted domain." : "Sunucuya güvenilmeyen bir alan adından ulaşıyorsunuz.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Lütfen yöneticiniz ile iletişime geçin. Eğer bu örneğin bir yöneticisi iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını yapılandırın. Bu yapılandırmanın bir örneği config/config.sample.php dosyasında verilmiştir.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Yapılandırmanıza bağlı olarak, bir yönetici olarak bu alan adına güvenmek için aşağıdaki düğmeyi de kullanabilirsiniz.", "Add \"%s\" as trusted domain" : "\"%s\" alan adını güvenilir olarak ekle", "App update required" : "Uygulama güncellemesi gerekli", diff --git a/core/l10n/tr.json b/core/l10n/tr.json index 601772dfd38..66f3a83f7ed 100644 --- a/core/l10n/tr.json +++ b/core/l10n/tr.json @@ -260,7 +260,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Eğer bu ileti görünmeye devam ederse veya beklenmedik şekilde ortaya çıkmışsa sistem yöneticinizle iletişime geçin.", "Thank you for your patience." : "Sabrınız için teşekkür ederiz.", "You are accessing the server from an untrusted domain." : "Sunucuya güvenilmeyen bir alan adından ulaşıyorsunuz.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Lütfen yöneticiniz ile iletişime geçin. Eğer bu örneğin bir yöneticisi iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını yapılandırın. Bu yapılandırmanın bir örneği config/config.sample.php dosyasında verilmiştir.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Yapılandırmanıza bağlı olarak, bir yönetici olarak bu alan adına güvenmek için aşağıdaki düğmeyi de kullanabilirsiniz.", "Add \"%s\" as trusted domain" : "\"%s\" alan adını güvenilir olarak ekle", "App update required" : "Uygulama güncellemesi gerekli", diff --git a/core/l10n/uk.js b/core/l10n/uk.js index 36f7e8aa5bd..bd1c5f679e8 100644 --- a/core/l10n/uk.js +++ b/core/l10n/uk.js @@ -236,6 +236,7 @@ OC.L10N.register( "Finishing …" : "Завершується ...", "Need help?" : "Потрібна допомога?", "See the documentation" : "Дивіться документацію", + "Hey there,

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

" : "Агов,

просто повідомляємо вам, що %s поділився »%s« з вами.
Перегляньте!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ця програма вимагає увімкнений JavaScript для коректної роботи. Будь ласка, {linkstart} Увімкніть JavaScript {linkend} та перезавантажте сторінку.", "Log out" : "Вихід", "Search" : "Пошук", @@ -246,13 +247,11 @@ OC.L10N.register( "Log in" : "Увійти", "Wrong password. Reset it?" : "Невірний пароль. Скинути його?", "Alternative Logins" : "Альтернативні імена користувача", - "Hey there,

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

" : "Агов,

просто повідомляємо вам, що %s поділився »%s« з вами.
Перегляньте!

", "This ownCloud instance is currently in single user mode." : "Сервер ownCloud в даний час працює в однокористувацькому режимі.", "This means only administrators can use the instance." : "Це означає, що тільки адміністратори можуть використовувати сервер.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Зверніться до вашого системного адміністратора якщо це повідомлення не зникає або з'являється несподівано.", "Thank you for your patience." : "Дякуємо за ваше терпіння.", "You are accessing the server from an untrusted domain." : "Ви намагаєтеся отримати доступ до сервера з непідтвердженого домену.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Будь ласка, зверніться до адміністратора. Якщо ви є адміністратором цього серверу, ви можете налаштувати опцію \"trusted_domain\" в конфігураційному файлі config/config.php. Приклад конфігурації знаходиться в файлі config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Залежно від конфігурації Ви як адміністратор можете додати цей домен у список довірених, використовуйте кнопку нижче.", "Add \"%s\" as trusted domain" : "Додати \"%s\" як довірений домен", "App update required" : "Додаток потребує оновлення", diff --git a/core/l10n/uk.json b/core/l10n/uk.json index 77e9389e147..4b95c4a92cd 100644 --- a/core/l10n/uk.json +++ b/core/l10n/uk.json @@ -234,6 +234,7 @@ "Finishing …" : "Завершується ...", "Need help?" : "Потрібна допомога?", "See the documentation" : "Дивіться документацію", + "Hey there,

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

" : "Агов,

просто повідомляємо вам, що %s поділився »%s« з вами.
Перегляньте!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ця програма вимагає увімкнений JavaScript для коректної роботи. Будь ласка, {linkstart} Увімкніть JavaScript {linkend} та перезавантажте сторінку.", "Log out" : "Вихід", "Search" : "Пошук", @@ -244,13 +245,11 @@ "Log in" : "Увійти", "Wrong password. Reset it?" : "Невірний пароль. Скинути його?", "Alternative Logins" : "Альтернативні імена користувача", - "Hey there,

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

" : "Агов,

просто повідомляємо вам, що %s поділився »%s« з вами.
Перегляньте!

", "This ownCloud instance is currently in single user mode." : "Сервер ownCloud в даний час працює в однокористувацькому режимі.", "This means only administrators can use the instance." : "Це означає, що тільки адміністратори можуть використовувати сервер.", "Contact your system administrator if this message persists or appeared unexpectedly." : "Зверніться до вашого системного адміністратора якщо це повідомлення не зникає або з'являється несподівано.", "Thank you for your patience." : "Дякуємо за ваше терпіння.", "You are accessing the server from an untrusted domain." : "Ви намагаєтеся отримати доступ до сервера з непідтвердженого домену.", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Будь ласка, зверніться до адміністратора. Якщо ви є адміністратором цього серверу, ви можете налаштувати опцію \"trusted_domain\" в конфігураційному файлі config/config.php. Приклад конфігурації знаходиться в файлі config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Залежно від конфігурації Ви як адміністратор можете додати цей домен у список довірених, використовуйте кнопку нижче.", "Add \"%s\" as trusted domain" : "Додати \"%s\" як довірений домен", "App update required" : "Додаток потребує оновлення", diff --git a/core/l10n/zh_CN.js b/core/l10n/zh_CN.js index 2aade6d5532..d2f2b6cb33b 100644 --- a/core/l10n/zh_CN.js +++ b/core/l10n/zh_CN.js @@ -242,6 +242,7 @@ OC.L10N.register( "Finishing …" : "正在结束 ...", "Need help?" : "需要帮助?", "See the documentation" : "查看文档", + "Hey there,

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

" : "嗨、你好,

只想让你知道 %s 分享了 %s 给你。
现在查看!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "对于正确的操作,该应用要求 JavaScript 。请 {linkstart} 打开 JavaScript {linkend} ,然后重新载入页面。", "Log out" : "注销", "Search" : "搜索", @@ -252,13 +253,11 @@ OC.L10N.register( "Log in" : "登录", "Wrong password. Reset it?" : "密码错误。要重置么?", "Alternative Logins" : "其他登录方式", - "Hey there,

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

" : "嗨、你好,

只想让你知道 %s 分享了 %s 给你。
现在查看!

", "This ownCloud instance is currently in single user mode." : "当前ownCloud实例运行在单用户模式下。", "This means only administrators can use the instance." : "这意味着只有管理员才能在实例上操作。", "Contact your system administrator if this message persists or appeared unexpectedly." : "如果这个消息一直存在或不停出现,请联系你的系统管理员。", "Thank you for your patience." : "感谢让你久等了。", "You are accessing the server from an untrusted domain." : "您正在访问来自不信任域名的服务器。", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "请联系你的系统管理员。如果你是系统管理员,配置config/config.php文件中参数\"trusted_domain\" 设置。可以在config/config.sample.php文件中找到例子。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "基于你的配置,作为系统管理员,你可能还能点击下面的按钮来信任这个域。", "Add \"%s\" as trusted domain" : "添加 \"%s\"为信任域", "App update required" : "必须的应用更新", diff --git a/core/l10n/zh_CN.json b/core/l10n/zh_CN.json index c4f171bb068..4d7cbb12d1f 100644 --- a/core/l10n/zh_CN.json +++ b/core/l10n/zh_CN.json @@ -240,6 +240,7 @@ "Finishing …" : "正在结束 ...", "Need help?" : "需要帮助?", "See the documentation" : "查看文档", + "Hey there,

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

" : "嗨、你好,

只想让你知道 %s 分享了 %s 给你。
现在查看!

", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "对于正确的操作,该应用要求 JavaScript 。请 {linkstart} 打开 JavaScript {linkend} ,然后重新载入页面。", "Log out" : "注销", "Search" : "搜索", @@ -250,13 +251,11 @@ "Log in" : "登录", "Wrong password. Reset it?" : "密码错误。要重置么?", "Alternative Logins" : "其他登录方式", - "Hey there,

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

" : "嗨、你好,

只想让你知道 %s 分享了 %s 给你。
现在查看!

", "This ownCloud instance is currently in single user mode." : "当前ownCloud实例运行在单用户模式下。", "This means only administrators can use the instance." : "这意味着只有管理员才能在实例上操作。", "Contact your system administrator if this message persists or appeared unexpectedly." : "如果这个消息一直存在或不停出现,请联系你的系统管理员。", "Thank you for your patience." : "感谢让你久等了。", "You are accessing the server from an untrusted domain." : "您正在访问来自不信任域名的服务器。", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "请联系你的系统管理员。如果你是系统管理员,配置config/config.php文件中参数\"trusted_domain\" 设置。可以在config/config.sample.php文件中找到例子。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "基于你的配置,作为系统管理员,你可能还能点击下面的按钮来信任这个域。", "Add \"%s\" as trusted domain" : "添加 \"%s\"为信任域", "App update required" : "必须的应用更新", diff --git a/core/l10n/zh_TW.js b/core/l10n/zh_TW.js index 93138a93e92..bf83a8eb3db 100644 --- a/core/l10n/zh_TW.js +++ b/core/l10n/zh_TW.js @@ -268,7 +268,6 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "若這個訊息持續出現,請聯絡系統管理員", "Thank you for your patience." : "感謝您的耐心", "You are accessing the server from an untrusted domain." : "你正在從一個未信任的網域存取伺服器", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "請聯絡您的系統管理員,如果您就是系統管理員,請設定 config/config.php 中的 \"trusted_domain\" 選項。範例設定提供於 config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "依照設定而定,您身為系統管理員可能也可以使用底下的按鈕來信任這個網域", "Add \"%s\" as trusted domain" : "將 %s 加入到信任的網域", "App update required" : "需要更新應用程式", diff --git a/core/l10n/zh_TW.json b/core/l10n/zh_TW.json index ea5fdbda2d0..89ed5f0c086 100644 --- a/core/l10n/zh_TW.json +++ b/core/l10n/zh_TW.json @@ -266,7 +266,6 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "若這個訊息持續出現,請聯絡系統管理員", "Thank you for your patience." : "感謝您的耐心", "You are accessing the server from an untrusted domain." : "你正在從一個未信任的網域存取伺服器", - "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "請聯絡您的系統管理員,如果您就是系統管理員,請設定 config/config.php 中的 \"trusted_domain\" 選項。範例設定提供於 config/config.sample.php", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "依照設定而定,您身為系統管理員可能也可以使用底下的按鈕來信任這個網域", "Add \"%s\" as trusted domain" : "將 %s 加入到信任的網域", "App update required" : "需要更新應用程式", -- GitLab From 84e5b76d3cac223330fc1bc5a83349bd8d23b5f8 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 2 Nov 2015 15:04:56 +0100 Subject: [PATCH 026/344] Add getOwner() method to FileInfo and Node API --- lib/public/files/node.php | 8 ++++++++ lib/public/files/storage.php | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/lib/public/files/node.php b/lib/public/files/node.php index aa1115f8c28..866b9b6f61f 100644 --- a/lib/public/files/node.php +++ b/lib/public/files/node.php @@ -225,4 +225,12 @@ interface Node extends FileInfo { * @since 6.0.0 */ public function getName(); + + /** + * Get the file owner + * + * @since 9.0.0 + * @return string + */ + public function getOwner(); } diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php index 1c520026777..c42a2d05bc3 100644 --- a/lib/public/files/storage.php +++ b/lib/public/files/storage.php @@ -462,4 +462,10 @@ interface Storage { * @param bool $isAvailable */ public function setAvailability($isAvailable); + + /** + * @param $path path for which to retrieve the owner + * @since 9.0.0 + */ + public function getOwner($path); } -- GitLab From a3fc40921b20a3fcc1c7260f4abfcadc5a8c1d13 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 13 Nov 2015 11:47:32 +0100 Subject: [PATCH 027/344] Add fake locker plugin for WebDAVFS WebDAVFS as used by Finder requires a Class 2 compatible WebDAV server. This change introduces a fake locking provider which will simply advertise Locking support when a request originates from WebDAVFS. It will also return successful LOCK and UNLOCK responses. --- apps/dav/appinfo/v1/publicwebdav.php | 3 +- apps/dav/appinfo/v1/webdav.php | 3 +- .../lib/connector/sabre/fakelockerplugin.php | 159 ++++++++++++++++ .../dav/lib/connector/sabre/serverfactory.php | 43 ++++- apps/dav/lib/server.php | 6 + .../connector/sabre/FakeLockerPluginTest.php | 173 ++++++++++++++++++ .../sabre/requesttest/requesttest.php | 4 +- 7 files changed, 386 insertions(+), 5 deletions(-) create mode 100644 apps/dav/lib/connector/sabre/fakelockerplugin.php create mode 100644 apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php index 5bdfd94e658..cf0488038d3 100644 --- a/apps/dav/appinfo/v1/publicwebdav.php +++ b/apps/dav/appinfo/v1/publicwebdav.php @@ -39,7 +39,8 @@ $serverFactory = new OCA\DAV\Connector\Sabre\ServerFactory( \OC::$server->getUserSession(), \OC::$server->getMountManager(), \OC::$server->getTagManager(), - \OC::$server->getEventDispatcher() + \OC::$server->getEventDispatcher(), + \OC::$server->getRequest() ); $requestUri = \OC::$server->getRequest()->getRequestUri(); diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php index f28736f1f01..8324f962b8e 100644 --- a/apps/dav/appinfo/v1/webdav.php +++ b/apps/dav/appinfo/v1/webdav.php @@ -40,7 +40,8 @@ $serverFactory = new \OCA\DAV\Connector\Sabre\ServerFactory( \OC::$server->getUserSession(), \OC::$server->getMountManager(), \OC::$server->getTagManager(), - \OC::$server->getEventDispatcher() + \OC::$server->getEventDispatcher(), + \OC::$server->getRequest() ); // Backends diff --git a/apps/dav/lib/connector/sabre/fakelockerplugin.php b/apps/dav/lib/connector/sabre/fakelockerplugin.php new file mode 100644 index 00000000000..493d3b0ade4 --- /dev/null +++ b/apps/dav/lib/connector/sabre/fakelockerplugin.php @@ -0,0 +1,159 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\DAV\Connector\Sabre; + +use Sabre\DAV\Locks\LockInfo; +use Sabre\DAV\Property\LockDiscovery; +use Sabre\DAV\Property\SupportedLock; +use Sabre\DAV\ServerPlugin; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; +use Sabre\DAV\PropFind; +use Sabre\DAV\INode; + +/** + * Class FakeLockerPlugin is a plugin only used when connections come in from + * OS X via Finder. The fake locking plugin does emulate Class 2 WebDAV support + * (locking of files) which allows Finder to access the storage in write mode as + * well. + * + * No real locking is performed, instead the plugin just returns always positive + * responses. + * + * @see https://github.com/owncloud/core/issues/17732 + * @package OCA\DAV\Connector\Sabre + */ +class FakeLockerPlugin extends ServerPlugin { + /** @var \Sabre\DAV\Server */ + private $server; + + /** {@inheritDoc} */ + public function initialize(\Sabre\DAV\Server $server) { + $this->server = $server; + $this->server->on('method:LOCK', [$this, 'fakeLockProvider'], 1); + $this->server->on('method:UNLOCK', [$this, 'fakeUnlockProvider'], 1); + $server->on('propFind', [$this, 'propFind']); + $server->on('validateTokens', [$this, 'validateTokens']); + } + + /** + * Indicate that we support LOCK and UNLOCK + * + * @param string $path + * @return array + */ + public function getHTTPMethods($path) { + return [ + 'LOCK', + 'UNLOCK', + ]; + } + + /** + * Indicate that we support locking + * + * @return array + */ + function getFeatures() { + return [2]; + } + + /** + * Return some dummy response for PROPFIND requests with regard to locking + * + * @param PropFind $propFind + * @param INode $node + * @return void + */ + function propFind(PropFind $propFind, INode $node) { + $propFind->handle('{DAV:}supportedlock', function() { + return new SupportedLock(true); + }); + $propFind->handle('{DAV:}lockdiscovery', function() use ($propFind) { + return new LockDiscovery([]); + }); + } + + /** + * Mark a locking token always as valid + * + * @param RequestInterface $request + * @param array $conditions + */ + public function validateTokens(RequestInterface $request, &$conditions) { + foreach($conditions as &$fileCondition) { + if(isset($fileCondition['tokens'])) { + foreach($fileCondition['tokens'] as &$token) { + if(isset($token['token'])) { + if(substr($token['token'], 0, 16) === 'opaquelocktoken:') { + $token['validToken'] = true; + } + } + } + } + } + } + + /** + * Fakes a successful LOCK + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return bool + */ + public function fakeLockProvider(RequestInterface $request, + ResponseInterface $response) { + $dom = new \DOMDocument('1.0', 'utf-8'); + $prop = $dom->createElementNS('DAV:', 'd:prop'); + $dom->appendChild($prop); + + $lockDiscovery = $dom->createElementNS('DAV:', 'd:lockdiscovery'); + $prop->appendChild($lockDiscovery); + + $lockInfo = new LockInfo(); + $lockInfo->token = md5($request->getPath()); + $lockInfo->uri = $request->getPath(); + $lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY; + $lockInfo->timeout = 1800; + + $lockObj = new LockDiscovery([$lockInfo]); + $lockObj->serialize($this->server, $lockDiscovery); + + $response->setBody($dom->saveXML()); + + return false; + } + + /** + * Fakes a successful LOCK + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return bool + */ + public function fakeUnlockProvider(RequestInterface $request, + ResponseInterface $response) { + $response->setStatus(204); + $response->setHeader('Content-Length', '0'); + return false; + } +} diff --git a/apps/dav/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php index f67e949e802..a33acc9f00b 100644 --- a/apps/dav/lib/connector/sabre/serverfactory.php +++ b/apps/dav/lib/connector/sabre/serverfactory.php @@ -26,12 +26,41 @@ use OCP\Files\Mount\IMountManager; use OCP\IConfig; use OCP\IDBConnection; use OCP\ILogger; +use OCP\IRequest; use OCP\ITagManager; use OCP\IUserSession; use Sabre\DAV\Auth\Backend\BackendInterface; +use Sabre\DAV\Locks\Plugin; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class ServerFactory { + /** @var IConfig */ + private $config; + /** @var ILogger */ + private $logger; + /** @var IDBConnection */ + private $databaseConnection; + /** @var IUserSession */ + private $userSession; + /** @var IMountManager */ + private $mountManager; + /** @var ITagManager */ + private $tagManager; + /** @var EventDispatcherInterface */ + private $dispatcher; + /** @var IRequest */ + private $request; + + /** + * @param IConfig $config + * @param ILogger $logger + * @param IDBConnection $databaseConnection + * @param IUserSession $userSession + * @param IMountManager $mountManager + * @param ITagManager $tagManager + * @param EventDispatcherInterface $dispatcher + * @param IRequest $request + */ public function __construct( IConfig $config, ILogger $logger, @@ -39,7 +68,8 @@ class ServerFactory { IUserSession $userSession, IMountManager $mountManager, ITagManager $tagManager, - EventDispatcherInterface $dispatcher + EventDispatcherInterface $dispatcher, + IRequest $request ) { $this->config = $config; $this->logger = $logger; @@ -48,6 +78,7 @@ class ServerFactory { $this->mountManager = $mountManager; $this->tagManager = $tagManager; $this->dispatcher = $dispatcher; + $this->request = $request; } /** @@ -57,7 +88,10 @@ class ServerFactory { * @param callable $viewCallBack callback that should return the view for the dav endpoint * @return Server */ - public function createServer($baseUri, $requestUri, BackendInterface $authBackend, callable $viewCallBack) { + public function createServer($baseUri, + $requestUri, + BackendInterface $authBackend, + callable $viewCallBack) { // Fire up server $objectTree = new \OCA\DAV\Connector\Sabre\ObjectTree(); $server = new \OCA\DAV\Connector\Sabre\Server($objectTree); @@ -75,6 +109,11 @@ class ServerFactory { $server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger)); $server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin($objectTree)); $server->addPlugin(new \OCA\DAV\Connector\Sabre\ListenerPlugin($this->dispatcher)); + // Finder on OS X requires Class 2 WebDAV support (locking), since we do + // not provide locking we emulate it using a fake locking plugin. + if($this->request->isUserAgent(['/WebDAVFS/'])) { + $server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin()); + } // wait with registering these until auth is handled and the filesystem is setup $server->on('beforeMethod', function () use ($server, $objectTree, $viewCallBack) { diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index a92c9980f54..395544761ab 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -37,6 +37,12 @@ class Server { $this->server->addPlugin(new \Sabre\CardDAV\Plugin()); + // Finder on OS X requires Class 2 WebDAV support (locking), since we do + // not provide locking we emulate it using a fake locking plugin. + if($request->isUserAgent(['/WebDAVFS/'])) { + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin()); + } + // wait with registering these until auth is handled and the filesystem is setup $this->server->on('beforeMethod', function () { // custom properties plugin must be the last one diff --git a/apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php b/apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php new file mode 100644 index 00000000000..dfe8cc220a3 --- /dev/null +++ b/apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php @@ -0,0 +1,173 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\DAV\Tests\Unit\Connector\Sabre; + +use OCA\DAV\Connector\Sabre\FakeLockerPlugin; +use Test\TestCase; + +/** + * Class FakeLockerPluginTest + * + * @package OCA\DAV\Tests\Unit\Connector\Sabre + */ +class FakeLockerPluginTest extends TestCase { + /** @var FakeLockerPlugin */ + private $fakeLockerPlugin; + + public function setUp() { + parent::setUp(); + $this->fakeLockerPlugin = new FakeLockerPlugin(); + } + + public function testInitialize() { + /** @var \Sabre\DAV\Server $server */ + $server = $this->getMock('\Sabre\DAV\Server'); + $server + ->expects($this->at(0)) + ->method('on') + ->with('method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1); + $server + ->expects($this->at(1)) + ->method('on') + ->with('method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1); + $server + ->expects($this->at(2)) + ->method('on') + ->with('propFind', [$this->fakeLockerPlugin, 'propFind']); + $server + ->expects($this->at(3)) + ->method('on') + ->with('validateTokens', [$this->fakeLockerPlugin, 'validateTokens']); + + $this->fakeLockerPlugin->initialize($server); + } + + public function testGetHTTPMethods() { + $expected = [ + 'LOCK', + 'UNLOCK', + ]; + $this->assertSame($expected, $this->fakeLockerPlugin->getHTTPMethods('Test')); + } + + public function testGetFeatures() { + $expected = [ + 2, + ]; + $this->assertSame($expected, $this->fakeLockerPlugin->getFeatures()); + } + + public function testPropFind() { + $propFind = $this->getMockBuilder('\Sabre\DAV\PropFind') + ->disableOriginalConstructor() + ->getMock(); + $node = $this->getMock('\Sabre\DAV\INode'); + + $propFind->expects($this->at(0)) + ->method('handle') + ->with('{DAV:}supportedlock'); + $propFind->expects($this->at(1)) + ->method('handle') + ->with('{DAV:}lockdiscovery'); + + $this->fakeLockerPlugin->propFind($propFind, $node); + } + + public function tokenDataProvider() { + return [ + [ + [ + [ + 'tokens' => [ + [ + 'token' => 'aToken', + 'validToken' => false, + ], + [], + [ + 'token' => 'opaquelocktoken:asdf', + 'validToken' => false, + ] + ], + ] + ], + [ + [ + 'tokens' => [ + [ + 'token' => 'aToken', + 'validToken' => false, + ], + [], + [ + 'token' => 'opaquelocktoken:asdf', + 'validToken' => true, + ] + ], + ] + ], + ] + ]; + } + + /** + * @dataProvider tokenDataProvider + * @param array $input + * @param array $expected + */ + public function testValidateTokens(array $input, array $expected) { + $request = $this->getMock('\Sabre\HTTP\RequestInterface'); + $this->fakeLockerPlugin->validateTokens($request, $input); + $this->assertSame($expected, $input); + } + + public function testFakeLockProvider() { + $request = $this->getMock('\Sabre\HTTP\RequestInterface'); + $response = $this->getMock('\Sabre\HTTP\ResponseInterface'); + $server = $this->getMock('\Sabre\DAV\Server'); + $this->fakeLockerPlugin->initialize($server); + + $request->expects($this->exactly(2)) + ->method('getPath') + ->will($this->returnValue('MyPath')); + $response->expects($this->once()) + ->method('setBody') + ->with(' +MyPathinfinitySecond-1800opaquelocktoken:fe4f7f2437b151fbcb4e9f5c8118c6b1 +'); + + $this->assertSame(false, $this->fakeLockerPlugin->fakeLockProvider($request, $response)); + } + + public function testFakeUnlockProvider() { + $request = $this->getMock('\Sabre\HTTP\RequestInterface'); + $response = $this->getMock('\Sabre\HTTP\ResponseInterface'); + + $response->expects($this->once()) + ->method('setStatus') + ->with('204'); + $response->expects($this->once()) + ->method('setHeader') + ->with('Content-Length', '0'); + + $this->assertSame(false, $this->fakeLockerPlugin->fakeUnlockProvider($request, $response)); + } +} diff --git a/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php b/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php index d90cf6e19bc..a83f25c1585 100644 --- a/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php +++ b/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php @@ -46,7 +46,8 @@ abstract class RequestTest extends TestCase { \OC::$server->getUserSession(), \OC::$server->getMountManager(), \OC::$server->getTagManager(), - \OC::$server->getEventDispatcher() + \OC::$server->getEventDispatcher(), + $this->getMock('\OCP\IRequest') ); } @@ -67,6 +68,7 @@ abstract class RequestTest extends TestCase { * @param resource|string|null $body * @param array|null $headers * @return \Sabre\HTTP\Response + * @throws \Exception */ protected function request($view, $user, $password, $method, $url, $body = null, $headers = null) { if (is_string($body)) { -- GitLab From 1b409228ab62f5bb57fb9d73b4053d75b2835829 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Sat, 14 Nov 2015 01:55:13 -0500 Subject: [PATCH 028/344] [tx-robot] updated from transifex --- apps/files/l10n/el.js | 2 ++ apps/files/l10n/el.json | 2 ++ apps/files/l10n/fi_FI.js | 1 + apps/files/l10n/fi_FI.json | 1 + apps/files/l10n/it.js | 2 ++ apps/files/l10n/it.json | 2 ++ apps/files/l10n/ja.js | 2 ++ apps/files/l10n/ja.json | 2 ++ apps/files/l10n/sq.js | 3 +++ apps/files/l10n/sq.json | 3 +++ apps/user_ldap/l10n/el.js | 1 + apps/user_ldap/l10n/el.json | 1 + apps/user_ldap/l10n/fi_FI.js | 3 +++ apps/user_ldap/l10n/fi_FI.json | 3 +++ apps/user_ldap/l10n/it.js | 1 + apps/user_ldap/l10n/it.json | 1 + apps/user_ldap/l10n/ja.js | 1 + apps/user_ldap/l10n/ja.json | 1 + apps/user_ldap/l10n/sq.js | 1 + apps/user_ldap/l10n/sq.json | 1 + core/l10n/el.js | 1 + core/l10n/el.json | 1 + core/l10n/fi_FI.js | 1 + core/l10n/fi_FI.json | 1 + core/l10n/it.js | 1 + core/l10n/it.json | 1 + core/l10n/ja.js | 1 + core/l10n/ja.json | 1 + core/l10n/sq.js | 1 + core/l10n/sq.json | 1 + 30 files changed, 44 insertions(+) diff --git a/apps/files/l10n/el.js b/apps/files/l10n/el.js index 36066e9fe9c..6c8e2cbff33 100644 --- a/apps/files/l10n/el.js +++ b/apps/files/l10n/el.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Μέγιστο μέγεθος αποστολής", "max. possible: " : "μέγιστο δυνατό:", "Save" : "Αποθήκευση", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Με PHP-FPM μπορεί να χρειαστούν μέχρι και 5 λεπτά για να ενεργοποιηθούν οι αλλαγές.", + "Missing permissions to edit from here." : "Δεν υπάρχουν τα απαραίτητα δικαιώματα για να γίνει τροποποιήση σε αυτό το σημείο.", "Settings" : "Ρυθμίσεις", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε πρόσβαση στα αρχεία σας μέσω WebDAV", diff --git a/apps/files/l10n/el.json b/apps/files/l10n/el.json index 7f0ce4dfe38..ee9e4ebde54 100644 --- a/apps/files/l10n/el.json +++ b/apps/files/l10n/el.json @@ -104,6 +104,8 @@ "Maximum upload size" : "Μέγιστο μέγεθος αποστολής", "max. possible: " : "μέγιστο δυνατό:", "Save" : "Αποθήκευση", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Με PHP-FPM μπορεί να χρειαστούν μέχρι και 5 λεπτά για να ενεργοποιηθούν οι αλλαγές.", + "Missing permissions to edit from here." : "Δεν υπάρχουν τα απαραίτητα δικαιώματα για να γίνει τροποποιήση σε αυτό το σημείο.", "Settings" : "Ρυθμίσεις", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε πρόσβαση στα αρχεία σας μέσω WebDAV", diff --git a/apps/files/l10n/fi_FI.js b/apps/files/l10n/fi_FI.js index 447350e024f..79f3321577f 100644 --- a/apps/files/l10n/fi_FI.js +++ b/apps/files/l10n/fi_FI.js @@ -106,6 +106,7 @@ OC.L10N.register( "Maximum upload size" : "Lähetettävän tiedoston suurin sallittu koko", "max. possible: " : "suurin mahdollinen:", "Save" : "Tallenna", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "PHP-FPM:tä käyttäen muutoksien voimaantulossa saattaa kestää 5 minuuttia.", "Settings" : "Asetukset", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Käytä tätä osoitetta käyttääksesi tiedostojasi WebDAVin kautta", diff --git a/apps/files/l10n/fi_FI.json b/apps/files/l10n/fi_FI.json index aa30ccd433e..e46327c83fa 100644 --- a/apps/files/l10n/fi_FI.json +++ b/apps/files/l10n/fi_FI.json @@ -104,6 +104,7 @@ "Maximum upload size" : "Lähetettävän tiedoston suurin sallittu koko", "max. possible: " : "suurin mahdollinen:", "Save" : "Tallenna", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "PHP-FPM:tä käyttäen muutoksien voimaantulossa saattaa kestää 5 minuuttia.", "Settings" : "Asetukset", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Käytä tätä osoitetta käyttääksesi tiedostojasi WebDAVin kautta", diff --git a/apps/files/l10n/it.js b/apps/files/l10n/it.js index 7fdd7170887..4c6033e6caf 100644 --- a/apps/files/l10n/it.js +++ b/apps/files/l10n/it.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Dimensione massima caricamento", "max. possible: " : "numero mass.: ", "Save" : "Salva", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Con PHP-FPM potrebbe richiedere 5 minuti perché le modifiche siano applicate.", + "Missing permissions to edit from here." : "Permessi mancanti per modificare da qui.", "Settings" : "Impostazioni", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilizza questo indirizzo per accedere ai tuoi file con WebDAV", diff --git a/apps/files/l10n/it.json b/apps/files/l10n/it.json index 9e5bee70191..239b8dc399c 100644 --- a/apps/files/l10n/it.json +++ b/apps/files/l10n/it.json @@ -104,6 +104,8 @@ "Maximum upload size" : "Dimensione massima caricamento", "max. possible: " : "numero mass.: ", "Save" : "Salva", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Con PHP-FPM potrebbe richiedere 5 minuti perché le modifiche siano applicate.", + "Missing permissions to edit from here." : "Permessi mancanti per modificare da qui.", "Settings" : "Impostazioni", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilizza questo indirizzo per accedere ai tuoi file con WebDAV", diff --git a/apps/files/l10n/ja.js b/apps/files/l10n/ja.js index 53eb8dca351..be441c15ca1 100644 --- a/apps/files/l10n/ja.js +++ b/apps/files/l10n/ja.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "最大アップロードサイズ", "max. possible: " : "最大容量: ", "Save" : "保存", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "PHP-FPM の場合は値を変更後、反映されるのに5分程度かかります。", + "Missing permissions to edit from here." : "ここから編集するための権限がありません。", "Settings" : "設定", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "WebDAV経由でのファイルアクセスにはこのアドレスを利用してください", diff --git a/apps/files/l10n/ja.json b/apps/files/l10n/ja.json index 36983beafc2..58b4870369c 100644 --- a/apps/files/l10n/ja.json +++ b/apps/files/l10n/ja.json @@ -104,6 +104,8 @@ "Maximum upload size" : "最大アップロードサイズ", "max. possible: " : "最大容量: ", "Save" : "保存", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "PHP-FPM の場合は値を変更後、反映されるのに5分程度かかります。", + "Missing permissions to edit from here." : "ここから編集するための権限がありません。", "Settings" : "設定", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "WebDAV経由でのファイルアクセスにはこのアドレスを利用してください", diff --git a/apps/files/l10n/sq.js b/apps/files/l10n/sq.js index 9428855d9ee..5f0b3a8c936 100644 --- a/apps/files/l10n/sq.js +++ b/apps/files/l10n/sq.js @@ -70,6 +70,7 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "Depozita juaj është plot, kartelat s’mund të përditësohen ose njëkohësohen më!", "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Depozita e {owner} është thuasje plot ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Depozita juaj është thuajse plot ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["ka përputhje me '{filter}'","ka përputhje me '{filter}'"], "Path" : "Shteg", "_%n byte_::_%n bytes_" : ["%n bajt","%n bajte"], "Favorited" : "U kalua e parapëlqyer", @@ -105,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Madhësi maksimale ngarkimi", "max. possible: " : "maks. i mundshëm: ", "Save" : "Ruaje", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Me PHP-FPM mund të duhen 5 minuta që ndryshimet të hyjnë në fuqi.", + "Missing permissions to edit from here." : "Mungojnë lejet për të përpunuar që këtu.", "Settings" : "Rregullime", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Përdorni këtë adresë për të hyrë te Kartelat tuaja përmes WebDAV-it", diff --git a/apps/files/l10n/sq.json b/apps/files/l10n/sq.json index 65e87f42c1b..fceac2c5376 100644 --- a/apps/files/l10n/sq.json +++ b/apps/files/l10n/sq.json @@ -68,6 +68,7 @@ "Your storage is full, files can not be updated or synced anymore!" : "Depozita juaj është plot, kartelat s’mund të përditësohen ose njëkohësohen më!", "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Depozita e {owner} është thuasje plot ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Depozita juaj është thuajse plot ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["ka përputhje me '{filter}'","ka përputhje me '{filter}'"], "Path" : "Shteg", "_%n byte_::_%n bytes_" : ["%n bajt","%n bajte"], "Favorited" : "U kalua e parapëlqyer", @@ -103,6 +104,8 @@ "Maximum upload size" : "Madhësi maksimale ngarkimi", "max. possible: " : "maks. i mundshëm: ", "Save" : "Ruaje", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Me PHP-FPM mund të duhen 5 minuta që ndryshimet të hyjnë në fuqi.", + "Missing permissions to edit from here." : "Mungojnë lejet për të përpunuar që këtu.", "Settings" : "Rregullime", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Përdorni këtë adresë për të hyrë te Kartelat tuaja përmes WebDAV-it", diff --git a/apps/user_ldap/l10n/el.js b/apps/user_ldap/l10n/el.js index d8f825b8288..7ea629e673d 100644 --- a/apps/user_ldap/l10n/el.js +++ b/apps/user_ldap/l10n/el.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Αδυναμία ανίχνευσης Base DN, παρακαλώ να το εισάγετε χειροκίνητα.", "{nthServer}. Server" : "{nthServer}. Διακομιστής", "No object found in the given Base DN. Please revise." : "Δεν βρέθηκε αντικείμενο στο δηλωθέν Base DN. Παρακαλώ αναθεωρήστε.", + "More than 1,000 directory entries available." : "Είναι διαθέσιμες περισσότερες από 1.000 εγγραφές καταλόγου.", " entries available within the provided Base DN" : "διαθέσιμες καταχωρήσεις εντός του δηλωθέντος ", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Παρουσιάστηκε σφάλμα. Παρακαλούμε ελέγξτε το Base DN καθώς και τις ρυθμίσεις και τα διαπιστευτήρια σύνδεσης.", "Do you really want to delete the current Server Configuration?" : "Θέλετε να διαγράψετε τις τρέχουσες ρυθμίσεις του διακομιστή;", diff --git a/apps/user_ldap/l10n/el.json b/apps/user_ldap/l10n/el.json index 142ca58d844..338b0b8bad9 100644 --- a/apps/user_ldap/l10n/el.json +++ b/apps/user_ldap/l10n/el.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Αδυναμία ανίχνευσης Base DN, παρακαλώ να το εισάγετε χειροκίνητα.", "{nthServer}. Server" : "{nthServer}. Διακομιστής", "No object found in the given Base DN. Please revise." : "Δεν βρέθηκε αντικείμενο στο δηλωθέν Base DN. Παρακαλώ αναθεωρήστε.", + "More than 1,000 directory entries available." : "Είναι διαθέσιμες περισσότερες από 1.000 εγγραφές καταλόγου.", " entries available within the provided Base DN" : "διαθέσιμες καταχωρήσεις εντός του δηλωθέντος ", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Παρουσιάστηκε σφάλμα. Παρακαλούμε ελέγξτε το Base DN καθώς και τις ρυθμίσεις και τα διαπιστευτήρια σύνδεσης.", "Do you really want to delete the current Server Configuration?" : "Θέλετε να διαγράψετε τις τρέχουσες ρυθμίσεις του διακομιστή;", diff --git a/apps/user_ldap/l10n/fi_FI.js b/apps/user_ldap/l10n/fi_FI.js index 5091cb1d88e..96ed6a00c7d 100644 --- a/apps/user_ldap/l10n/fi_FI.js +++ b/apps/user_ldap/l10n/fi_FI.js @@ -22,6 +22,8 @@ OC.L10N.register( "Available groups" : "Käytettävissä olevat ryhmät", "Selected groups" : "Valitut ryhmät", "LDAP Filter:" : "LDAP-suodatin:", + "LDAP / AD Username:" : "LDAP-/AD-käyttäjätunnus:", + "LDAP / AD Email Address:" : "LDAP-/AD-sähköpostiosoite:", "Verify settings" : "Vahvista asetukset", "1. Server" : "1. Palvelin", "%s. Server:" : "%s. Palvelin:", @@ -34,6 +36,7 @@ OC.L10N.register( "Password" : "Salasana", "For anonymous access, leave DN and Password empty." : "Jos haluat mahdollistaa anonyymin pääsyn, jätä DN ja Salasana tyhjäksi ", "You can specify Base DN for users and groups in the Advanced tab" : "Voit määrittää käyttäjien ja ryhmien oletus DN:n (distinguished name) 'tarkemmat asetukset'-välilehdeltä ", + "Verify settings and count users" : "Vahvista asetukset ja laske käyttäjät", "Saving" : "Tallennetaan", "Back" : "Takaisin", "Continue" : "Jatka", diff --git a/apps/user_ldap/l10n/fi_FI.json b/apps/user_ldap/l10n/fi_FI.json index 54e12650166..e34fefaf93d 100644 --- a/apps/user_ldap/l10n/fi_FI.json +++ b/apps/user_ldap/l10n/fi_FI.json @@ -20,6 +20,8 @@ "Available groups" : "Käytettävissä olevat ryhmät", "Selected groups" : "Valitut ryhmät", "LDAP Filter:" : "LDAP-suodatin:", + "LDAP / AD Username:" : "LDAP-/AD-käyttäjätunnus:", + "LDAP / AD Email Address:" : "LDAP-/AD-sähköpostiosoite:", "Verify settings" : "Vahvista asetukset", "1. Server" : "1. Palvelin", "%s. Server:" : "%s. Palvelin:", @@ -32,6 +34,7 @@ "Password" : "Salasana", "For anonymous access, leave DN and Password empty." : "Jos haluat mahdollistaa anonyymin pääsyn, jätä DN ja Salasana tyhjäksi ", "You can specify Base DN for users and groups in the Advanced tab" : "Voit määrittää käyttäjien ja ryhmien oletus DN:n (distinguished name) 'tarkemmat asetukset'-välilehdeltä ", + "Verify settings and count users" : "Vahvista asetukset ja laske käyttäjät", "Saving" : "Tallennetaan", "Back" : "Takaisin", "Continue" : "Jatka", diff --git a/apps/user_ldap/l10n/it.js b/apps/user_ldap/l10n/it.js index 88a5ceea447..8bb42e1a72a 100644 --- a/apps/user_ldap/l10n/it.js +++ b/apps/user_ldap/l10n/it.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Impossibile rilevare il DN base, digitalo manualmente.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Nessun oggetto trovato nel DN base specificato. Controlla.", + "More than 1,000 directory entries available." : "Più di 1.000 cartelle disponibili.", " entries available within the provided Base DN" : "voci disponibili all'interno del DN base", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Si è verificato un errore. Controlla il DN base, così come le impostazioni di connessione e le credenziali.", "Do you really want to delete the current Server Configuration?" : "Vuoi davvero eliminare la configurazione attuale del server?", diff --git a/apps/user_ldap/l10n/it.json b/apps/user_ldap/l10n/it.json index cb8f6b11d73..73234261016 100644 --- a/apps/user_ldap/l10n/it.json +++ b/apps/user_ldap/l10n/it.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Impossibile rilevare il DN base, digitalo manualmente.", "{nthServer}. Server" : "{nthServer}. server", "No object found in the given Base DN. Please revise." : "Nessun oggetto trovato nel DN base specificato. Controlla.", + "More than 1,000 directory entries available." : "Più di 1.000 cartelle disponibili.", " entries available within the provided Base DN" : "voci disponibili all'interno del DN base", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Si è verificato un errore. Controlla il DN base, così come le impostazioni di connessione e le credenziali.", "Do you really want to delete the current Server Configuration?" : "Vuoi davvero eliminare la configurazione attuale del server?", diff --git a/apps/user_ldap/l10n/ja.js b/apps/user_ldap/l10n/ja.js index 3ba8bd8f2f3..e138c46e08e 100644 --- a/apps/user_ldap/l10n/ja.js +++ b/apps/user_ldap/l10n/ja.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "ベース DN を検出できませんでした。手動で入力してください。", "{nthServer}. Server" : "{nthServer}. サーバー", "No object found in the given Base DN. Please revise." : "指定されたベース DN でオブジェクトを見つけることができませんでした。修正をお願いします。", + "More than 1,000 directory entries available." : "1,000以上のディレクトリエントリが利用可能です。", " entries available within the provided Base DN" : "入力されたベースDNでエントリーが利用可能", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "エラーが発生しました。ベースDNをチェックし、接続設定と権限についても同様に確認してください。", "Do you really want to delete the current Server Configuration?" : "現在のサーバー設定を本当に削除してもよろしいですか?", diff --git a/apps/user_ldap/l10n/ja.json b/apps/user_ldap/l10n/ja.json index 64d40cd8e4a..ef69c48adcc 100644 --- a/apps/user_ldap/l10n/ja.json +++ b/apps/user_ldap/l10n/ja.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "ベース DN を検出できませんでした。手動で入力してください。", "{nthServer}. Server" : "{nthServer}. サーバー", "No object found in the given Base DN. Please revise." : "指定されたベース DN でオブジェクトを見つけることができませんでした。修正をお願いします。", + "More than 1,000 directory entries available." : "1,000以上のディレクトリエントリが利用可能です。", " entries available within the provided Base DN" : "入力されたベースDNでエントリーが利用可能", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "エラーが発生しました。ベースDNをチェックし、接続設定と権限についても同様に確認してください。", "Do you really want to delete the current Server Configuration?" : "現在のサーバー設定を本当に削除してもよろしいですか?", diff --git a/apps/user_ldap/l10n/sq.js b/apps/user_ldap/l10n/sq.js index 4ec40ef5957..4f0d1d3697c 100644 --- a/apps/user_ldap/l10n/sq.js +++ b/apps/user_ldap/l10n/sq.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "S’u zbulua dot DN Bazë, ju lutemi, jepeni dorazi.", "{nthServer}. Server" : "{nthServer}. Shërbyes", "No object found in the given Base DN. Please revise." : "Në DN Bazë të dhën s’u gjet objekt. Ju lutemi, rishikojeni.", + "More than 1,000 directory entries available." : "Më shumë se 1000 zëra të gatshëm.", " entries available within the provided Base DN" : " zëra të gatshëm brenda DN-së Bazë të dhënë", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ndodhi një gabim. Ju lutemi, kontrolloni DN-në Bazë, sie dhe rregullimet për lidhjen dhe kredencialet.", "Do you really want to delete the current Server Configuration?" : "Doni vërtet të fshihet Formësimi i tanishëm i Shërbyesit?", diff --git a/apps/user_ldap/l10n/sq.json b/apps/user_ldap/l10n/sq.json index 2e50290f18c..6045b61f57d 100644 --- a/apps/user_ldap/l10n/sq.json +++ b/apps/user_ldap/l10n/sq.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "S’u zbulua dot DN Bazë, ju lutemi, jepeni dorazi.", "{nthServer}. Server" : "{nthServer}. Shërbyes", "No object found in the given Base DN. Please revise." : "Në DN Bazë të dhën s’u gjet objekt. Ju lutemi, rishikojeni.", + "More than 1,000 directory entries available." : "Më shumë se 1000 zëra të gatshëm.", " entries available within the provided Base DN" : " zëra të gatshëm brenda DN-së Bazë të dhënë", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Ndodhi një gabim. Ju lutemi, kontrolloni DN-në Bazë, sie dhe rregullimet për lidhjen dhe kredencialet.", "Do you really want to delete the current Server Configuration?" : "Doni vërtet të fshihet Formësimi i tanishëm i Shërbyesit?", diff --git a/core/l10n/el.js b/core/l10n/el.js index b4a4b2efef7..2f264730565 100644 --- a/core/l10n/el.js +++ b/core/l10n/el.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Επικοινωνήστε με το διαχειριστή του συστήματος αν αυτό το μήνυμα συνεχίζει να εμφανίζεται ή εμφανίστηκε απρόσμενα.", "Thank you for your patience." : "Σας ευχαριστούμε για την υπομονή σας.", "You are accessing the server from an untrusted domain." : "Η προσπέλαση του διακομιστή γίνεται από μη έμπιστο τομέα.", + "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." : "Παρακαλώ επικοινωνήστε με το διαχειριστή του συστήματος. Αν είστε ο διαχειριστής, ρυθμίστε την επιλογή \"trusted_domain\" στο αρχείο config/config.php. Μπορείτε να βρείτε παράδειγμα στο αρχείο config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ανάλογα με τις ρυθμίσεις σας, σαν διαχειριστής θα μπορούσατε επίσης να χρησιμοποιήσετε το παρακάτω κουμπί για να εμπιστευθείτε αυτή την περιοχή.", "Add \"%s\" as trusted domain" : "Προσθήκη \"%s\" ως αξιόπιστη περιοχή", "App update required" : "Απαιτείται ενημέρωση εφαρμογής", diff --git a/core/l10n/el.json b/core/l10n/el.json index dfa81965cbc..cafa289fc32 100644 --- a/core/l10n/el.json +++ b/core/l10n/el.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Επικοινωνήστε με το διαχειριστή του συστήματος αν αυτό το μήνυμα συνεχίζει να εμφανίζεται ή εμφανίστηκε απρόσμενα.", "Thank you for your patience." : "Σας ευχαριστούμε για την υπομονή σας.", "You are accessing the server from an untrusted domain." : "Η προσπέλαση του διακομιστή γίνεται από μη έμπιστο τομέα.", + "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." : "Παρακαλώ επικοινωνήστε με το διαχειριστή του συστήματος. Αν είστε ο διαχειριστής, ρυθμίστε την επιλογή \"trusted_domain\" στο αρχείο config/config.php. Μπορείτε να βρείτε παράδειγμα στο αρχείο config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ανάλογα με τις ρυθμίσεις σας, σαν διαχειριστής θα μπορούσατε επίσης να χρησιμοποιήσετε το παρακάτω κουμπί για να εμπιστευθείτε αυτή την περιοχή.", "Add \"%s\" as trusted domain" : "Προσθήκη \"%s\" ως αξιόπιστη περιοχή", "App update required" : "Απαιτείται ενημέρωση εφαρμογής", diff --git a/core/l10n/fi_FI.js b/core/l10n/fi_FI.js index 28b9c98db67..6e4a2c438d9 100644 --- a/core/l10n/fi_FI.js +++ b/core/l10n/fi_FI.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Ota yhteys järjestelmän ylläpitäjään, jos tämä viesti ilmenee uudelleen tai odottamatta.", "Thank you for your patience." : "Kiitos kärsivällisyydestäsi.", "You are accessing the server from an untrusted domain." : "Olet yhteydessä palvelimeen epäluotettavasta verkko-osoitteesta.", + "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." : "Ota yhteys ylläpitoon. Jos olet tämän asennuksen ylläpitäjä, määritä \"trusted_domains\"-asetus config/config.php-tiedostossa. Esimerkkimääritys on tarjolla tiedostossa config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Riippuen määrityksistä, ylläpitäjänä saatat kyetä käyttämään alla olevaa painiketta luodaksesi luottamussuhteen tähän toimialueeseen.", "Add \"%s\" as trusted domain" : "Lisää \"%s\" luotetuksi toimialueeksi", "App update required" : "Sovelluksen päivittäminen vaaditaan", diff --git a/core/l10n/fi_FI.json b/core/l10n/fi_FI.json index 1a84873e6cc..bf88973a83c 100644 --- a/core/l10n/fi_FI.json +++ b/core/l10n/fi_FI.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Ota yhteys järjestelmän ylläpitäjään, jos tämä viesti ilmenee uudelleen tai odottamatta.", "Thank you for your patience." : "Kiitos kärsivällisyydestäsi.", "You are accessing the server from an untrusted domain." : "Olet yhteydessä palvelimeen epäluotettavasta verkko-osoitteesta.", + "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." : "Ota yhteys ylläpitoon. Jos olet tämän asennuksen ylläpitäjä, määritä \"trusted_domains\"-asetus config/config.php-tiedostossa. Esimerkkimääritys on tarjolla tiedostossa config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Riippuen määrityksistä, ylläpitäjänä saatat kyetä käyttämään alla olevaa painiketta luodaksesi luottamussuhteen tähän toimialueeseen.", "Add \"%s\" as trusted domain" : "Lisää \"%s\" luotetuksi toimialueeksi", "App update required" : "Sovelluksen päivittäminen vaaditaan", diff --git a/core/l10n/it.js b/core/l10n/it.js index d95b02b2841..873c8fb4fea 100644 --- a/core/l10n/it.js +++ b/core/l10n/it.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Contatta il tuo amministratore di sistema se questo messaggio persiste o appare inaspettatamente.", "Thank you for your patience." : "Grazie per la pazienza.", "You are accessing the server from an untrusted domain." : "Stai accedendo al server da un dominio non attendibile.", + "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." : "Contatta il tuo amministratore di sistema. Se sei un amministratore di questa istanza, configura l'impostazione \"trusted_domains\" in config/config.php. Una configurazione di esempio è disponibile in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "In base alla tua configurazione, come amministratore potrai utilizzare anche il pulsante in basso per rendere attendibile questo dominio.", "Add \"%s\" as trusted domain" : "Aggiungi \"%s\" come dominio attendibile", "App update required" : "Aggiornamento dell'applicazione richiesto", diff --git a/core/l10n/it.json b/core/l10n/it.json index 944a615653a..8dffade7400 100644 --- a/core/l10n/it.json +++ b/core/l10n/it.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Contatta il tuo amministratore di sistema se questo messaggio persiste o appare inaspettatamente.", "Thank you for your patience." : "Grazie per la pazienza.", "You are accessing the server from an untrusted domain." : "Stai accedendo al server da un dominio non attendibile.", + "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." : "Contatta il tuo amministratore di sistema. Se sei un amministratore di questa istanza, configura l'impostazione \"trusted_domains\" in config/config.php. Una configurazione di esempio è disponibile in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "In base alla tua configurazione, come amministratore potrai utilizzare anche il pulsante in basso per rendere attendibile questo dominio.", "Add \"%s\" as trusted domain" : "Aggiungi \"%s\" come dominio attendibile", "App update required" : "Aggiornamento dell'applicazione richiesto", diff --git a/core/l10n/ja.js b/core/l10n/ja.js index c1fef991cc5..225948366f6 100644 --- a/core/l10n/ja.js +++ b/core/l10n/ja.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。", "Thank you for your patience." : "しばらくお待ちください。", "You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。", + "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." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。", "Add \"%s\" as trusted domain" : "\"%s\" を信頼するドメイン名に追加", "App update required" : "アプリの更新が必要", diff --git a/core/l10n/ja.json b/core/l10n/ja.json index 99dfb583ccc..21cd77dacbb 100644 --- a/core/l10n/ja.json +++ b/core/l10n/ja.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。", "Thank you for your patience." : "しばらくお待ちください。", "You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。", + "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." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。", "Add \"%s\" as trusted domain" : "\"%s\" を信頼するドメイン名に追加", "App update required" : "アプリの更新が必要", diff --git a/core/l10n/sq.js b/core/l10n/sq.js index 7a3ba05abef..a40e56b9907 100644 --- a/core/l10n/sq.js +++ b/core/l10n/sq.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Nëse ky mesazh shfaqet vazhdimisht ose u shfaq papritmas, lidhuni me përgjegjësin e sistemit.", "Thank you for your patience." : "Ju faleminderit për durimin.", "You are accessing the server from an untrusted domain." : "Po hyni në shërbyes nga një përkatësi jo e besuar.", + "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." : "Ju lutemi, lidhuni me përgjegjësin tuaj. Nëse jeni një përgjegjës në këtë instancë, formësoni rregullimin \"trusted_domains\" te config/config.php. Një formësim shembull jepet te config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Në varësi të formësimit tuaj, si administrator mundet gjithashtu të jeni në gjendje të përdorni butonin më poshtë për ta besuar këtë përkatësi.", "Add \"%s\" as trusted domain" : "Shtojeni \"%s\" si përkatësi të besuar", "App update required" : "Lypset përditësim aplikacioni", diff --git a/core/l10n/sq.json b/core/l10n/sq.json index 057510bfe94..4284bb9a40e 100644 --- a/core/l10n/sq.json +++ b/core/l10n/sq.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Nëse ky mesazh shfaqet vazhdimisht ose u shfaq papritmas, lidhuni me përgjegjësin e sistemit.", "Thank you for your patience." : "Ju faleminderit për durimin.", "You are accessing the server from an untrusted domain." : "Po hyni në shërbyes nga një përkatësi jo e besuar.", + "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." : "Ju lutemi, lidhuni me përgjegjësin tuaj. Nëse jeni një përgjegjës në këtë instancë, formësoni rregullimin \"trusted_domains\" te config/config.php. Një formësim shembull jepet te config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Në varësi të formësimit tuaj, si administrator mundet gjithashtu të jeni në gjendje të përdorni butonin më poshtë për ta besuar këtë përkatësi.", "Add \"%s\" as trusted domain" : "Shtojeni \"%s\" si përkatësi të besuar", "App update required" : "Lypset përditësim aplikacioni", -- GitLab From fee6847f48f7aef8a06ce723455df8dc1c488d5c Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Sat, 14 Nov 2015 14:52:51 +0100 Subject: [PATCH 029/344] [Avatar] No need to setup FS for avatar tests --- tests/core/avatar/avatarcontrollertest.php | 99 +++++++++------------- 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/tests/core/avatar/avatarcontrollertest.php b/tests/core/avatar/avatarcontrollertest.php index 929a4e5f91d..948a432d2ed 100644 --- a/tests/core/avatar/avatarcontrollertest.php +++ b/tests/core/avatar/avatarcontrollertest.php @@ -28,6 +28,10 @@ use OCP\AppFramework\Http; use OCP\Image; use OCP\Files\Folder; use OCP\Files\File; +use OCP\IUser; +use OCP\IAvatar; + +use Test\Traits\UserTrait; /** * Overwrite is_uploaded_file in this namespace to allow proper unit testing of @@ -43,79 +47,53 @@ function is_uploaded_file($filename) { * @package OC\Core\Avatar */ class AvatarControllerTest extends \Test\TestCase { + use UserTrait; /** @var IAppContainer */ private $container; - /** @var string */ - private $user; - /** @var string */ - private $oldUser; /** @var AvatarController */ private $avatarController; - + /** @var IAvatar */ private $avatarMock; - + /** @var IUser */ private $userMock; - + protected function setUp() { + parent::setUp(); + $this->createUser('userid', 'pass'); + $this->loginAsUser('userid'); + $app = new Application; $this->container = $app->getContainer(); $this->container['AppName'] = 'core'; - $this->container['AvatarManager'] = $this->getMockBuilder('OCP\IAvatarManager') - ->disableOriginalConstructor()->getMock(); + $this->container['AvatarManager'] = $this->getMock('OCP\IAvatarManager'); $this->container['Cache'] = $this->getMockBuilder('OC\Cache\File') ->disableOriginalConstructor()->getMock(); - $this->container['L10N'] = $this->getMockBuilder('OCP\IL10N') - ->disableOriginalConstructor()->getMock(); + $this->container['L10N'] = $this->getMock('OCP\IL10N'); $this->container['L10N']->method('t')->will($this->returnArgument(0)); - $this->container['UserManager'] = $this->getMockBuilder('OCP\IUserManager') - ->disableOriginalConstructor()->getMock(); - $this->container['UserSession'] = $this->getMockBuilder('OCP\IUserSession') - ->disableOriginalConstructor()->getMock(); - $this->container['Request'] = $this->getMockBuilder('OCP\IRequest') - ->disableOriginalConstructor()->getMock(); - $this->container['UserFolder'] = $this->getMockBuilder('OCP\Files\Folder') - ->disableOriginalConstructor()->getMock(); - $this->container['Logger'] = $this->getMockBuilder('OCP\ILogger') - ->disableOriginalConstructor()->getMock(); + $this->container['UserManager'] = $this->getMock('OCP\IUserManager'); + $this->container['UserSession'] = $this->getMock('OCP\IUserSession'); + $this->container['Request'] = $this->getMock('OCP\IRequest'); + $this->container['UserFolder'] = $this->getMock('OCP\Files\Folder'); + $this->container['Logger'] = $this->getMock('OCP\ILogger'); - $this->avatarMock = $this->getMockBuilder('OCP\IAvatar') - ->disableOriginalConstructor()->getMock(); - $this->userMock = $this->getMockBuilder('OCP\IUser') - ->disableOriginalConstructor()->getMock(); + $this->avatarMock = $this->getMock('OCP\IAvatar'); + $this->userMock = $this->getMock('OCP\IUser'); $this->avatarController = $this->container['AvatarController']; - // Store current User - $this->oldUser = \OC_User::getUser(); - - // Create a dummy user - $this->user = $this->getUniqueID('user'); - - OC::$server->getUserManager()->createUser($this->user, $this->user); - $this->loginAsUser($this->user); - // Configure userMock - $this->userMock->method('getDisplayName')->willReturn($this->user); - $this->userMock->method('getUID')->willReturn($this->user); + $this->userMock->method('getDisplayName')->willReturn('displayName'); + $this->userMock->method('getUID')->willReturn('userId'); $this->container['UserManager']->method('get') - ->willReturnMap([[$this->user, $this->userMock]]); + ->willReturnMap([['userId', $this->userMock]]); $this->container['UserSession']->method('getUser')->willReturn($this->userMock); } public function tearDown() { - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - Filesystem::tearDown(); - OC::$server->getUserManager()->get($this->user)->delete(); - \OC_User::setIncognitoMode(false); - - \OC::$server->getSession()->set('public_link_authenticated', ''); - - // Set old user - \OC_User::setUserId($this->oldUser); - \OC_Util::setupFS($this->oldUser); + $this->logout(); + parent::tearDown(); } /** @@ -123,29 +101,32 @@ class AvatarControllerTest extends \Test\TestCase { */ public function testGetAvatarNoAvatar() { $this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock); - $response = $this->avatarController->getAvatar($this->user, 32); + $response = $this->avatarController->getAvatar('userId', 32); //Comment out until JS is fixed //$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); $this->assertEquals(Http::STATUS_OK, $response->getStatus()); - $this->assertEquals($this->user, $response->getData()['data']['displayname']); + $this->assertEquals('displayName', $response->getData()['data']['displayname']); } /** * Fetch the user's avatar */ public function testGetAvatar() { - $image = new Image(OC::$SERVERROOT.'/tests/data/testimage.jpg'); + $image = $this->getMock('OCP\IImage'); + $image->method('data')->willReturn('image data'); + $image->method('mimeType')->willReturn('image type'); + $this->avatarMock->method('get')->willReturn($image); $this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock); - $response = $this->avatarController->getAvatar($this->user, 32); + $response = $this->avatarController->getAvatar('userId', 32); $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + $this->assertArrayHasKey('Content-Type', $response->getHeaders()); + $this->assertEquals('image type', $response->getHeaders()['Content-Type']); - $image2 = new Image($response->getData()); - $this->assertEquals($image->mimeType(), $image2->mimeType()); - $this->assertEquals(crc32($response->getData()), $response->getEtag()); + $this->assertEquals(crc32('image data'), $response->getEtag()); } /** @@ -155,7 +136,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->avatarMock->method('get')->willReturn(null); $this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock); - $response = $this->avatarController->getAvatar($this->user . 'doesnotexist', 32); + $response = $this->avatarController->getAvatar('userDoesnotexist', 32); //Comment out until JS is fixed //$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); @@ -173,7 +154,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock); - $this->avatarController->getAvatar($this->user, 32); + $this->avatarController->getAvatar('userId', 32); } /** @@ -186,7 +167,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock); - $this->avatarController->getAvatar($this->user, 0); + $this->avatarController->getAvatar('userId', 0); } /** @@ -199,7 +180,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock); - $this->avatarController->getAvatar($this->user, 2049); + $this->avatarController->getAvatar('userId', 2049); } /** -- GitLab From 19d0884b56ddcce055a03bf155d757c8b4bfb01f Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Sun, 15 Nov 2015 01:55:08 -0500 Subject: [PATCH 030/344] [tx-robot] updated from transifex --- apps/files/l10n/cs_CZ.js | 2 ++ apps/files/l10n/cs_CZ.json | 2 ++ apps/files/l10n/fr.js | 2 ++ apps/files/l10n/fr.json | 2 ++ apps/files/l10n/pt_BR.js | 2 ++ apps/files/l10n/pt_BR.json | 2 ++ apps/files/l10n/zh_TW.js | 14 +++++++------- apps/files/l10n/zh_TW.json | 14 +++++++------- apps/user_ldap/l10n/cs_CZ.js | 1 + apps/user_ldap/l10n/cs_CZ.json | 1 + apps/user_ldap/l10n/fr.js | 1 + apps/user_ldap/l10n/fr.json | 1 + apps/user_ldap/l10n/pt_BR.js | 1 + apps/user_ldap/l10n/pt_BR.json | 1 + core/l10n/cs_CZ.js | 1 + core/l10n/cs_CZ.json | 1 + core/l10n/fr.js | 1 + core/l10n/fr.json | 1 + core/l10n/pt_BR.js | 1 + core/l10n/pt_BR.json | 1 + 20 files changed, 38 insertions(+), 14 deletions(-) diff --git a/apps/files/l10n/cs_CZ.js b/apps/files/l10n/cs_CZ.js index f93b1f5d7a1..3c6bdc05a1b 100644 --- a/apps/files/l10n/cs_CZ.js +++ b/apps/files/l10n/cs_CZ.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Maximální velikost pro odesílání", "max. possible: " : "největší možná: ", "Save" : "Uložit", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Při použití PHP-FPM může změna nastavení trvat až 5 minut od uložení.", + "Missing permissions to edit from here." : "Pro úpravy v aktuálním náhledu chybí oprávnění.", "Settings" : "Nastavení", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Použijte tuto adresu pro přístup k vašim souborům přes WebDAV", diff --git a/apps/files/l10n/cs_CZ.json b/apps/files/l10n/cs_CZ.json index 7daf7a492da..bf9170f2ee3 100644 --- a/apps/files/l10n/cs_CZ.json +++ b/apps/files/l10n/cs_CZ.json @@ -104,6 +104,8 @@ "Maximum upload size" : "Maximální velikost pro odesílání", "max. possible: " : "největší možná: ", "Save" : "Uložit", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Při použití PHP-FPM může změna nastavení trvat až 5 minut od uložení.", + "Missing permissions to edit from here." : "Pro úpravy v aktuálním náhledu chybí oprávnění.", "Settings" : "Nastavení", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Použijte tuto adresu pro přístup k vašim souborům přes WebDAV", diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js index d00f33391d4..e068b3c45ba 100644 --- a/apps/files/l10n/fr.js +++ b/apps/files/l10n/fr.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Taille max. d'envoi", "max. possible: " : "Max. possible :", "Save" : "Sauvegarder", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Avec PHP-FPM il peut se passer 5 minutes pour que les changements soient appliqués.", + "Missing permissions to edit from here." : "Manque de permissions pour éditer à partir d'ici.", "Settings" : "Paramètres", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilisez cette adresse pour accéder à vos fichiers par WebDAV", diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json index 9d30823e265..a297b3525d1 100644 --- a/apps/files/l10n/fr.json +++ b/apps/files/l10n/fr.json @@ -104,6 +104,8 @@ "Maximum upload size" : "Taille max. d'envoi", "max. possible: " : "Max. possible :", "Save" : "Sauvegarder", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Avec PHP-FPM il peut se passer 5 minutes pour que les changements soient appliqués.", + "Missing permissions to edit from here." : "Manque de permissions pour éditer à partir d'ici.", "Settings" : "Paramètres", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Utilisez cette adresse pour accéder à vos fichiers par WebDAV", diff --git a/apps/files/l10n/pt_BR.js b/apps/files/l10n/pt_BR.js index 158ef08608d..b7a2196db63 100644 --- a/apps/files/l10n/pt_BR.js +++ b/apps/files/l10n/pt_BR.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Tamanho máximo para envio", "max. possible: " : "max. possível:", "Save" : "Salvar", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Com PHP-FPM pode demorar 5 minutos para que as alterações sejam aplicadas.", + "Missing permissions to edit from here." : "Faltando permissões para editar a partir daqui.", "Settings" : "Configurações", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use este endereço para ter acesso aos seus Arquivos via WebDAV", diff --git a/apps/files/l10n/pt_BR.json b/apps/files/l10n/pt_BR.json index af539480d95..335b50a2d7d 100644 --- a/apps/files/l10n/pt_BR.json +++ b/apps/files/l10n/pt_BR.json @@ -104,6 +104,8 @@ "Maximum upload size" : "Tamanho máximo para envio", "max. possible: " : "max. possível:", "Save" : "Salvar", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Com PHP-FPM pode demorar 5 minutos para que as alterações sejam aplicadas.", + "Missing permissions to edit from here." : "Faltando permissões para editar a partir daqui.", "Settings" : "Configurações", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Use este endereço para ter acesso aos seus Arquivos via WebDAV", diff --git a/apps/files/l10n/zh_TW.js b/apps/files/l10n/zh_TW.js index aba0261047a..c38488d3087 100644 --- a/apps/files/l10n/zh_TW.js +++ b/apps/files/l10n/zh_TW.js @@ -7,7 +7,7 @@ OC.L10N.register( "Could not move %s - File with this name already exists" : "無法移動 %s ,同名的檔案已經存在", "Could not move %s" : "無法移動 %s", "Permission denied" : "存取被拒", - "The target folder has been moved or deleted." : "目標資料夾已經被搬移或刪除。", + "The target folder has been moved or deleted." : "目標資料夾已經被搬移或刪除", "The name %s is already used in the folder %s. Please choose a different name." : "%s 已經被使用於資料夾 %s ,請換一個名字", "Error when creating the file" : "建立檔案失敗", "Error when creating the folder" : "建立資料夾失敗", @@ -62,7 +62,7 @@ OC.L10N.register( "_%n file_::_%n files_" : ["%n 個檔案"], "{dirs} and {files}" : "{dirs} 和 {files}", "You don’t have permission to upload or create files here" : "您沒有權限在這裡上傳或建立檔案", - "_Uploading %n file_::_Uploading %n files_" : ["%n 個檔案正在上傳"], + "_Uploading %n file_::_Uploading %n files_" : ["正在上傳 %n 個檔案"], "New" : "新增", "\"{name}\" is an invalid file name." : "{name} 是無效的檔名", "File name cannot be empty." : "檔名不能為空", @@ -94,11 +94,11 @@ OC.L10N.register( "%2$s changed %1$s" : "%2$s 已變更了 %1$s", "You deleted %1$s" : "您刪除了 %1$s", "%2$s deleted %1$s" : "%2$s 已刪除 %1$s", - "You restored %1$s" : "您恢復了 %1$s", - "%2$s restored %1$s" : "%2$s 已恢復了 %1$s", + "You restored %1$s" : "您還原了 %1$s", + "%2$s restored %1$s" : "%2$s 還原了 %1$s", "Changed by %2$s" : "由 %2$s 改動", "Deleted by %2$s" : "由 %2$s 刪除", - "Restored by %2$s" : "由 %2$s 復原", + "Restored by %2$s" : "由 %2$s 還原", "%s could not be renamed as it has been deleted" : "%s 已經被刪除了所以無法重新命名", "%s could not be renamed" : "無法重新命名 %s", "Upload (max. %s)" : "上傳(至多 %s)", @@ -115,8 +115,8 @@ OC.L10N.register( "No entries found in this folder" : "在此資料夾中沒有任何項目", "Select all" : "全選", "Upload too large" : "上傳過大", - "The files you are trying to upload exceed the maximum size for file uploads on this server." : "您試圖上傳的檔案大小超過伺服器的限制。", - "Files are being scanned, please wait." : "正在掃描檔案,請稍等。", + "The files you are trying to upload exceed the maximum size for file uploads on this server." : "您試圖上傳的檔案大小超過伺服器的限制", + "Files are being scanned, please wait." : "正在掃描檔案,請稍等", "Currently scanning" : "正在掃描", "No favorites" : "沒有最愛", "Files and folders you mark as favorite will show up here" : "您標記為最愛的檔案與資料夾將會顯示在這裡" diff --git a/apps/files/l10n/zh_TW.json b/apps/files/l10n/zh_TW.json index 4e4f7d0a871..8a408b5ffad 100644 --- a/apps/files/l10n/zh_TW.json +++ b/apps/files/l10n/zh_TW.json @@ -5,7 +5,7 @@ "Could not move %s - File with this name already exists" : "無法移動 %s ,同名的檔案已經存在", "Could not move %s" : "無法移動 %s", "Permission denied" : "存取被拒", - "The target folder has been moved or deleted." : "目標資料夾已經被搬移或刪除。", + "The target folder has been moved or deleted." : "目標資料夾已經被搬移或刪除", "The name %s is already used in the folder %s. Please choose a different name." : "%s 已經被使用於資料夾 %s ,請換一個名字", "Error when creating the file" : "建立檔案失敗", "Error when creating the folder" : "建立資料夾失敗", @@ -60,7 +60,7 @@ "_%n file_::_%n files_" : ["%n 個檔案"], "{dirs} and {files}" : "{dirs} 和 {files}", "You don’t have permission to upload or create files here" : "您沒有權限在這裡上傳或建立檔案", - "_Uploading %n file_::_Uploading %n files_" : ["%n 個檔案正在上傳"], + "_Uploading %n file_::_Uploading %n files_" : ["正在上傳 %n 個檔案"], "New" : "新增", "\"{name}\" is an invalid file name." : "{name} 是無效的檔名", "File name cannot be empty." : "檔名不能為空", @@ -92,11 +92,11 @@ "%2$s changed %1$s" : "%2$s 已變更了 %1$s", "You deleted %1$s" : "您刪除了 %1$s", "%2$s deleted %1$s" : "%2$s 已刪除 %1$s", - "You restored %1$s" : "您恢復了 %1$s", - "%2$s restored %1$s" : "%2$s 已恢復了 %1$s", + "You restored %1$s" : "您還原了 %1$s", + "%2$s restored %1$s" : "%2$s 還原了 %1$s", "Changed by %2$s" : "由 %2$s 改動", "Deleted by %2$s" : "由 %2$s 刪除", - "Restored by %2$s" : "由 %2$s 復原", + "Restored by %2$s" : "由 %2$s 還原", "%s could not be renamed as it has been deleted" : "%s 已經被刪除了所以無法重新命名", "%s could not be renamed" : "無法重新命名 %s", "Upload (max. %s)" : "上傳(至多 %s)", @@ -113,8 +113,8 @@ "No entries found in this folder" : "在此資料夾中沒有任何項目", "Select all" : "全選", "Upload too large" : "上傳過大", - "The files you are trying to upload exceed the maximum size for file uploads on this server." : "您試圖上傳的檔案大小超過伺服器的限制。", - "Files are being scanned, please wait." : "正在掃描檔案,請稍等。", + "The files you are trying to upload exceed the maximum size for file uploads on this server." : "您試圖上傳的檔案大小超過伺服器的限制", + "Files are being scanned, please wait." : "正在掃描檔案,請稍等", "Currently scanning" : "正在掃描", "No favorites" : "沒有最愛", "Files and folders you mark as favorite will show up here" : "您標記為最愛的檔案與資料夾將會顯示在這裡" diff --git a/apps/user_ldap/l10n/cs_CZ.js b/apps/user_ldap/l10n/cs_CZ.js index 6aa15ebc918..e78755719b7 100644 --- a/apps/user_ldap/l10n/cs_CZ.js +++ b/apps/user_ldap/l10n/cs_CZ.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Nelze automaticky detekovat Base DN, zadejte prosím ručně.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "V zadané Base DN nebyl objekt nalezen. Ověřte.", + "More than 1,000 directory entries available." : "Je dostupných více než 1000 adresářů.", " entries available within the provided Base DN" : "záznamů dostupných v zadané Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Došlo k chybě. Ověře prosím Base DN společně s nastavením připojení a přihlašovacími údaji.", "Do you really want to delete the current Server Configuration?" : "Opravdu si přejete smazat současné nastavení serveru?", diff --git a/apps/user_ldap/l10n/cs_CZ.json b/apps/user_ldap/l10n/cs_CZ.json index a2eae7dae20..37e56cda1a7 100644 --- a/apps/user_ldap/l10n/cs_CZ.json +++ b/apps/user_ldap/l10n/cs_CZ.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Nelze automaticky detekovat Base DN, zadejte prosím ručně.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "V zadané Base DN nebyl objekt nalezen. Ověřte.", + "More than 1,000 directory entries available." : "Je dostupných více než 1000 adresářů.", " entries available within the provided Base DN" : "záznamů dostupných v zadané Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Došlo k chybě. Ověře prosím Base DN společně s nastavením připojení a přihlašovacími údaji.", "Do you really want to delete the current Server Configuration?" : "Opravdu si přejete smazat současné nastavení serveru?", diff --git a/apps/user_ldap/l10n/fr.js b/apps/user_ldap/l10n/fr.js index 4a7b2631b79..a013589cff2 100644 --- a/apps/user_ldap/l10n/fr.js +++ b/apps/user_ldap/l10n/fr.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Impossible de détecter le DN de base, veuillez le spécifier manuellement", "{nthServer}. Server" : "{nthServer}. Serveur", "No object found in the given Base DN. Please revise." : "Aucun objet trouvé dans le DN de base spécifié. Veuillez le vérifier.", + "More than 1,000 directory entries available." : "Il y a plus de 1 000 entrées de répertoire disponibles.", " entries available within the provided Base DN" : "entrées disponibles dans le DN de base spécifié", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Une erreur est survenue. Veuillez vérifier le DN de base, ainsi que les paramètres de connexion et les informations d'identification", "Do you really want to delete the current Server Configuration?" : "Êtes-vous sûr de vouloir effacer la configuration serveur actuelle ?", diff --git a/apps/user_ldap/l10n/fr.json b/apps/user_ldap/l10n/fr.json index 344bbaf7282..0b6c076f0d3 100644 --- a/apps/user_ldap/l10n/fr.json +++ b/apps/user_ldap/l10n/fr.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Impossible de détecter le DN de base, veuillez le spécifier manuellement", "{nthServer}. Server" : "{nthServer}. Serveur", "No object found in the given Base DN. Please revise." : "Aucun objet trouvé dans le DN de base spécifié. Veuillez le vérifier.", + "More than 1,000 directory entries available." : "Il y a plus de 1 000 entrées de répertoire disponibles.", " entries available within the provided Base DN" : "entrées disponibles dans le DN de base spécifié", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Une erreur est survenue. Veuillez vérifier le DN de base, ainsi que les paramètres de connexion et les informations d'identification", "Do you really want to delete the current Server Configuration?" : "Êtes-vous sûr de vouloir effacer la configuration serveur actuelle ?", diff --git a/apps/user_ldap/l10n/pt_BR.js b/apps/user_ldap/l10n/pt_BR.js index 3254610be2a..e027c930ceb 100644 --- a/apps/user_ldap/l10n/pt_BR.js +++ b/apps/user_ldap/l10n/pt_BR.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Não foi possível detectar a Base DN, por favor entre manualmente.", "{nthServer}. Server" : "Servidor {nthServer}.", "No object found in the given Base DN. Please revise." : "Nenhum objeto encontrado ba Base DN informada. Por favor revise.", + "More than 1,000 directory entries available." : "Mais de 1.000 entradas disponíveis no diretório.", " entries available within the provided Base DN" : "entradas disponíveis na Base DN disponibilizada", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Um erro ocorreu. Por favor verifique a Base DN, e também a conexção e credenciais.", "Do you really want to delete the current Server Configuration?" : "Você quer realmente deletar as atuais Configurações de Servidor?", diff --git a/apps/user_ldap/l10n/pt_BR.json b/apps/user_ldap/l10n/pt_BR.json index de03f9778d0..8251fa082a6 100644 --- a/apps/user_ldap/l10n/pt_BR.json +++ b/apps/user_ldap/l10n/pt_BR.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Não foi possível detectar a Base DN, por favor entre manualmente.", "{nthServer}. Server" : "Servidor {nthServer}.", "No object found in the given Base DN. Please revise." : "Nenhum objeto encontrado ba Base DN informada. Por favor revise.", + "More than 1,000 directory entries available." : "Mais de 1.000 entradas disponíveis no diretório.", " entries available within the provided Base DN" : "entradas disponíveis na Base DN disponibilizada", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Um erro ocorreu. Por favor verifique a Base DN, e também a conexção e credenciais.", "Do you really want to delete the current Server Configuration?" : "Você quer realmente deletar as atuais Configurações de Servidor?", diff --git a/core/l10n/cs_CZ.js b/core/l10n/cs_CZ.js index 086b100f0b4..8f6f3b38d9e 100644 --- a/core/l10n/cs_CZ.js +++ b/core/l10n/cs_CZ.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktujte prosím správce systému, pokud se tato zpráva objevuje opakovaně nebo nečekaně.", "Thank you for your patience." : "Děkujeme za vaši trpělivost.", "You are accessing the server from an untrusted domain." : "Přistupujete na server z nedůvěryhodné domény.", + "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." : "Kontaktujte prosím svého správce. Pokud spravujete tuto instalaci, nastavte \"trusted_domains\" v souboru config/config.php. Příklad konfigurace najdete v souboru config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "V závislosti na vaší konfiguraci vám může být, jako správci, umožněno použití tlačítka níže k označení této domény jako důvěryhodné.", "Add \"%s\" as trusted domain" : "Přidat \"%s\" jako důvěryhodnou doménu", "App update required" : "Vyžadována aktualizace aplikace", diff --git a/core/l10n/cs_CZ.json b/core/l10n/cs_CZ.json index 8f6430785a5..024e00159b3 100644 --- a/core/l10n/cs_CZ.json +++ b/core/l10n/cs_CZ.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktujte prosím správce systému, pokud se tato zpráva objevuje opakovaně nebo nečekaně.", "Thank you for your patience." : "Děkujeme za vaši trpělivost.", "You are accessing the server from an untrusted domain." : "Přistupujete na server z nedůvěryhodné domény.", + "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." : "Kontaktujte prosím svého správce. Pokud spravujete tuto instalaci, nastavte \"trusted_domains\" v souboru config/config.php. Příklad konfigurace najdete v souboru config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "V závislosti na vaší konfiguraci vám může být, jako správci, umožněno použití tlačítka níže k označení této domény jako důvěryhodné.", "Add \"%s\" as trusted domain" : "Přidat \"%s\" jako důvěryhodnou doménu", "App update required" : "Vyžadována aktualizace aplikace", diff --git a/core/l10n/fr.js b/core/l10n/fr.js index e25840a7afc..5a73540f141 100644 --- a/core/l10n/fr.js +++ b/core/l10n/fr.js @@ -269,6 +269,7 @@ 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.", "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, il faut configurer la variable \"trusted_domains\" dans le fichier config/config.php. Un exemple de configuration est fournit dans le fichier config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En fonction de votre configuration, en tant qu'administrateur vous pouvez également utiliser le bouton ci-dessous pour approuver ce domaine.", "Add \"%s\" as trusted domain" : "Ajouter \"%s\" à la liste des domaines approuvés", "App update required" : "Mise à jour de l'application nécessaire", diff --git a/core/l10n/fr.json b/core/l10n/fr.json index 0d86fa37d5a..088381169db 100644 --- a/core/l10n/fr.json +++ b/core/l10n/fr.json @@ -267,6 +267,7 @@ "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.", "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, il faut configurer la variable \"trusted_domains\" dans le fichier config/config.php. Un exemple de configuration est fournit dans le fichier config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "En fonction de votre configuration, en tant qu'administrateur vous pouvez également utiliser le bouton ci-dessous pour approuver ce domaine.", "Add \"%s\" as trusted domain" : "Ajouter \"%s\" à la liste des domaines approuvés", "App update required" : "Mise à jour de l'application nécessaire", diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index 44850a9f00b..4c5528163ec 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte o seu administrador do sistema se esta mensagem persistir ou aparecer inesperadamente.", "Thank you for your patience." : "Obrigado pela sua paciência.", "You are accessing the server from an untrusted domain." : "Você está acessando o servidor a partir de um domínio não confiável.", + "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." : "Por favor entre em contato com o administrador. Se você é um administrador deste exemplo, configure a definição \"trusted_domains\" em config/config.php. Um exemplo de configuração é fornecido em config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da configuração, como administrador, você também pode ser capaz de usar o botão abaixo para confiar neste domínio.", "Add \"%s\" as trusted domain" : "Adicionar \"%s\" como um domínio confiavel", "App update required" : "Atualização de aplicativo é requerida", diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 20300cf2343..023119c0fb1 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Contacte o seu administrador do sistema se esta mensagem persistir ou aparecer inesperadamente.", "Thank you for your patience." : "Obrigado pela sua paciência.", "You are accessing the server from an untrusted domain." : "Você está acessando o servidor a partir de um domínio não confiável.", + "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." : "Por favor entre em contato com o administrador. Se você é um administrador deste exemplo, configure a definição \"trusted_domains\" em config/config.php. Um exemplo de configuração é fornecido em config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Dependendo da configuração, como administrador, você também pode ser capaz de usar o botão abaixo para confiar neste domínio.", "Add \"%s\" as trusted domain" : "Adicionar \"%s\" como um domínio confiavel", "App update required" : "Atualização de aplicativo é requerida", -- GitLab From ae58409f2209e647dd69510142ff3cda53124f63 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Mon, 16 Nov 2015 01:54:50 -0500 Subject: [PATCH 031/344] [tx-robot] updated from transifex --- apps/user_ldap/l10n/nl.js | 1 + apps/user_ldap/l10n/nl.json | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/user_ldap/l10n/nl.js b/apps/user_ldap/l10n/nl.js index f546cfd8150..27f6dd9ffc7 100644 --- a/apps/user_ldap/l10n/nl.js +++ b/apps/user_ldap/l10n/nl.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Kon basis DN niet vaststellen, voer de gegevens handmatig in.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Geen object gevonden in de basis DN. Review instellingen.", + "More than 1,000 directory entries available." : "Meer dan 1000 directory namen beschikbaar.", " entries available within the provided Base DN" : "accounts beschikbaar binnen de provider Basis DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Er trad een fout op. Controleer de Basis DN en de verbindingsinstellingen en inloggegevens.", "Do you really want to delete the current Server Configuration?" : "Wilt u werkelijk de huidige Serverconfiguratie verwijderen?", diff --git a/apps/user_ldap/l10n/nl.json b/apps/user_ldap/l10n/nl.json index fc58e43347d..c98d7aa64dc 100644 --- a/apps/user_ldap/l10n/nl.json +++ b/apps/user_ldap/l10n/nl.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Kon basis DN niet vaststellen, voer de gegevens handmatig in.", "{nthServer}. Server" : "{nthServer}. Server", "No object found in the given Base DN. Please revise." : "Geen object gevonden in de basis DN. Review instellingen.", + "More than 1,000 directory entries available." : "Meer dan 1000 directory namen beschikbaar.", " entries available within the provided Base DN" : "accounts beschikbaar binnen de provider Basis DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Er trad een fout op. Controleer de Basis DN en de verbindingsinstellingen en inloggegevens.", "Do you really want to delete the current Server Configuration?" : "Wilt u werkelijk de huidige Serverconfiguratie verwijderen?", -- GitLab From b1abef77e484adb5417f5b662cda79fca69426c1 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Mon, 16 Nov 2015 11:16:38 +0100 Subject: [PATCH 032/344] Update strengthify to 0.4.2 * includes local changes (ported them to upstream - see #10625) * tipsy -> tooltip * re-renders the element on scroll of a parent - fixes #20454 --- bower.json | 2 +- core/vendor/strengthify/.bower.json | 10 ++-- core/vendor/strengthify/LICENSE | 2 +- core/vendor/strengthify/jquery.strengthify.js | 55 ++++++++++--------- core/vendor/strengthify/strengthify.css | 6 +- 5 files changed, 39 insertions(+), 36 deletions(-) diff --git a/bower.json b/bower.json index 1fe270d9f3c..e8bb9a35f32 100644 --- a/bower.json +++ b/bower.json @@ -24,7 +24,7 @@ "select2": "~3.4.8", "zxcvbn": "*", "snapjs": "~2.0.0-rc1", - "strengthify": "0.4.1", + "strengthify": "0.4.2", "underscore": "~1.8.0", "bootstrap": "~3.3.5", "backbone": "~1.2.1" diff --git a/core/vendor/strengthify/.bower.json b/core/vendor/strengthify/.bower.json index b86b43f17b7..d0baec6ed73 100644 --- a/core/vendor/strengthify/.bower.json +++ b/core/vendor/strengthify/.bower.json @@ -1,6 +1,6 @@ { "name": "strengthify", - "version": "0.4.1", + "version": "0.4.2", "homepage": "https://github.com/MorrisJobke/strengthify", "authors": [ "Morris Jobke " @@ -8,13 +8,13 @@ "description": "Combine jQuery and zxcvbn to create a password strength meter.", "main": "jquery.strengthify.js", "license": "MIT", - "_release": "0.4.1", + "_release": "0.4.2", "_resolution": { "type": "version", - "tag": "0.4.1", - "commit": "fe9d1c80156d3fcdd16434ebc789007d045c1d1f" + "tag": "v0.4.2", + "commit": "b3df9344d829063564cdced3c6328b001bc4bad1" }, "_source": "git://github.com/MorrisJobke/strengthify.git", - "_target": "0.4.1", + "_target": "0.4.2", "_originalSource": "strengthify" } \ No newline at end of file diff --git a/core/vendor/strengthify/LICENSE b/core/vendor/strengthify/LICENSE index 3c04738f789..b249b595978 100644 --- a/core/vendor/strengthify/LICENSE +++ b/core/vendor/strengthify/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013 Morris Jobke +Copyright (c) 2013-2015 Morris Jobke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/core/vendor/strengthify/jquery.strengthify.js b/core/vendor/strengthify/jquery.strengthify.js index 4fcc4d7c7c4..26d06a5d301 100644 --- a/core/vendor/strengthify/jquery.strengthify.js +++ b/core/vendor/strengthify/jquery.strengthify.js @@ -1,15 +1,15 @@ /** * Strengthify - show the weakness of a password (uses zxcvbn for this) - * https://github.com/kabum/strengthify + * https://github.com/MorrisJobke/strengthify * - * Version: 0.4.1 - * Author: Morris Jobke (github.com/kabum) + * Version: 0.4.2 + * Author: Morris Jobke (github.com/MorrisJobke) * * License: * * The MIT License (MIT) * - * Copyright (c) 2013 Morris Jobke + * Copyright (c) 2013-2015 Morris Jobke * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -43,23 +43,9 @@ 'Perfect' ] }, - options = $.extend(defaults, paramOptions); - - // add elements - $('.strengthify-wrapper') - .append('

') - .append('
') - .append('
') - .append('
') - .append('
'); - - $.ajax({ - cache: true, - dataType: 'script', - url: options.zxcvbn - }).done(function() { - me.bind('keyup input change', function() { - var password = $(this).val(), + options = $.extend(defaults, paramOptions), + drawStrengthify = function() { + var password = $(me).val(), // hide strengthigy if no input is provided opacity = (password === '') ? 0 : 1, // calculate result @@ -107,15 +93,15 @@ $wrapper.attr( 'title', options.titles[result.score] - ).tipsy({ + ).tooltip({ + placement: 'bottom', trigger: 'manual', - opacity: opacity - }).tipsy( + }).tooltip( 'show' ); if(opacity === 0) { - $wrapper.tipsy( + $wrapper.tooltip( 'hide' ); } @@ -125,7 +111,24 @@ $container.css('width', 0); } - }); + }; + + // add elements + $('.strengthify-wrapper') + .append('
') + .append('
') + .append('
') + .append('
') + .append('
'); + + me.parents().on('scroll', drawStrengthify); + + $.ajax({ + cache: true, + dataType: 'script', + url: options.zxcvbn + }).done(function() { + me.bind('keyup input change', drawStrengthify); }); return me; diff --git a/core/vendor/strengthify/strengthify.css b/core/vendor/strengthify/strengthify.css index 9340270ecfb..5555cbdf334 100644 --- a/core/vendor/strengthify/strengthify.css +++ b/core/vendor/strengthify/strengthify.css @@ -1,7 +1,7 @@ /** * Strengthify - show the weakness of a password (uses zxcvbn for this) - * https://github.com/kabum/strengthify - * Version: 0.3 + * https://github.com/MorrisJobke/strengthify + * Version: 0.4.2 * License: The MIT License (MIT) * Copyright (c) 2013 Morris Jobke */ @@ -45,4 +45,4 @@ } .password-good { background-color: #3C3; -} \ No newline at end of file +} -- GitLab From cc1db4ba87d407472a396766866abd35ecf79565 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 16 Nov 2015 13:11:32 +0100 Subject: [PATCH 033/344] assume pgsql >=9 if checking the version fails --- lib/private/util.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/private/util.php b/lib/private/util.php index 4c151d63639..28546ab279a 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -858,12 +858,9 @@ class OC_Util { } } } catch (\Doctrine\DBAL\DBALException $e) { - \OCP\Util::logException('core', $e); - $errors[] = array( - 'error' => $l->t('Error occurred while checking PostgreSQL version'), - 'hint' => $l->t('Please make sure you have PostgreSQL >= 9 or' - . ' check the logs for more information about the error') - ); + $logger = \OC::$server->getLogger(); + $logger->warning('Error occurred while checking PostgreSQL version, assuming >= 9'); + $logger->logException($e); } } return $errors; -- GitLab From 2b13c5db0f6116858ee6e118e8ca22d73d764e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 31 Oct 2015 01:28:21 +0100 Subject: [PATCH 034/344] Introducing CalDAV into core --- apps/dav/appinfo/database.xml | 387 ++++++ apps/dav/appinfo/info.xml | 2 +- apps/dav/lib/caldav/caldavbackend.php | 1136 +++++++++++++++++ apps/dav/lib/rootcollection.php | 19 +- apps/dav/lib/server.php | 10 + .../tests/unit/caldav/caldavbackendtest.php | 325 +++++ 6 files changed, 1872 insertions(+), 7 deletions(-) create mode 100644 apps/dav/lib/caldav/caldavbackend.php create mode 100644 apps/dav/tests/unit/caldav/caldavbackendtest.php diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml index f3fd5079949..5e2dad097e4 100644 --- a/apps/dav/appinfo/database.xml +++ b/apps/dav/appinfo/database.xml @@ -183,4 +183,391 @@ CREATE TABLE addressbookchanges ( + + + + *dbprefix*calendarobjects + + + id + integer + 0 + true + 1 + true + 11 + + + calendardata + blob + + + uri + text + + + calendarid + integer + true + true + + + lastmodified + integer + true + + + etag + text + 32 + + + size + integer + true + true + 11 + + + componenttype + text + + + firstoccurence + integer + true + + + lastoccurence + integer + true + + + uid + text + + + calobjects_index + true + + calendarid + + + uri + + + +
+ + + *dbprefix*calendars + + + id + integer + 0 + true + 1 + true + 11 + + + principaluri + text + + + displayname + text + + + uri + text + + + synctoken + integer + 1 + true + true + + + description + text + + + calendarorder + integer + 0 + true + true + + + calendarcolor + text + + + timezone + text + + + components + text + + + transparent + integer + 1 + true + 0 + + + calendars_index + true + + principaluri + + + uri + + + +
+ + + *dbprefix*calendarchanges + + + id + integer + 0 + true + 1 + true + 11 + + + uri + text + + + synctoken + integer + 1 + true + true + + + calendarid + integer + true + + + operation + integer + true + 1 + + + + calendarid_synctoken + + calendarid + + + synctoken + + + + +
+ + + + *dbprefix*calendarsubscriptions + + + id + integer + 0 + true + 1 + true + 11 + + + uri + text + + + principaluri + text + + + source + text + + + displayname + text + 100 + + + refreshrate + text + 10 + + + calendarorder + integer + 0 + true + true + + + calendarcolor + text + + + striptodos + integer + 1 + + + stripalarms + integer + 1 + + + stripattachments + integer + 1 + + + lastmodified + integer + true + + + calsub_index + true + + principaluri + + + uri + + + +
+ + + + *dbprefix*schedulingobjects + + + id + integer + 0 + true + 1 + true + 11 + + + principaluri + text + + + calendardata + blob + + + uri + text + + + lastmodified + integer + true + + + etag + text + 32 + + + size + integer + true + true + 11 + + + +
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 11025115691..5f681e784fc 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ ownCloud WebDAV endpoint AGPL owncloud.org - 0.1.2 + 0.1.3 9.0 true diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php new file mode 100644 index 00000000000..cd41fd1f044 --- /dev/null +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -0,0 +1,1136 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\DAV\CalDAV; + +use Sabre\CalDAV\Backend\AbstractBackend; +use Sabre\CalDAV\Backend\SchedulingSupport; +use Sabre\CalDAV\Backend\SubscriptionSupport; +use Sabre\CalDAV\Backend\SyncSupport; +use Sabre\CalDAV\Plugin; +use Sabre\CalDAV\Property\ScheduleCalendarTransp; +use Sabre\CalDAV\Property\SupportedCalendarComponentSet; +use Sabre\DAV; +use Sabre\DAV\Exception\Forbidden; +use Sabre\VObject\DateTimeParser; +use Sabre\VObject\Reader; +use Sabre\VObject\RecurrenceIterator; + +/** + * Class CalDavBackend + * + * Code is heavily inspired by https://github.com/fruux/sabre-dav/blob/master/lib/CalDAV/Backend/PDO.php + * + * @package OCA\DAV\CalDAV + */ +class CalDavBackend extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport { + + /** + * We need to specify a max date, because we need to stop *somewhere* + * + * On 32 bit system the maximum for a signed integer is 2147483647, so + * MAX_DATE cannot be higher than date('Y-m-d', 2147483647) which results + * in 2038-01-19 to avoid problems when the date is converted + * to a unix timestamp. + */ + const MAX_DATE = '2038-01-01'; + + /** + * List of CalDAV properties, and how they map to database fieldnames + * Add your own properties by simply adding on to this array. + * + * Note that only string-based properties are supported here. + * + * @var array + */ + public $propertyMap = [ + '{DAV:}displayname' => 'displayname', + '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description', + '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone', + '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder', + '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor', + ]; + + /** + * List of subscription properties, and how they map to database fieldnames. + * + * @var array + */ + public $subscriptionPropertyMap = [ + '{DAV:}displayname' => 'displayname', + '{http://apple.com/ns/ical/}refreshrate' => 'refreshrate', + '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder', + '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor', + '{http://calendarserver.org/ns/}subscribed-strip-todos' => 'striptodos', + '{http://calendarserver.org/ns/}subscribed-strip-alarms' => 'stripalarms', + '{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments', + ]; + + public function __construct(\OCP\IDBConnection $db) { + $this->db = $db; + } + + /** + * Returns a list of calendars for a principal. + * + * Every project is an array with the following keys: + * * id, a unique id that will be used by other functions to modify the + * calendar. This can be the same as the uri or a database key. + * * uri, which the basename of the uri with which the calendar is + * accessed. + * * principaluri. The owner of the calendar. Almost always the same as + * principalUri passed to this method. + * + * Furthermore it can contain webdav properties in clark notation. A very + * common one is '{DAV:}displayname'. + * + * Many clients also require: + * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set + * For this property, you can just return an instance of + * Sabre\CalDAV\Property\SupportedCalendarComponentSet. + * + * If you return {http://sabredav.org/ns}read-only and set the value to 1, + * ACL will automatically be put in read-only mode. + * + * @param string $principalUri + * @return array + */ + function getCalendarsForUser($principalUri) { + $fields = array_values($this->propertyMap); + $fields[] = 'id'; + $fields[] = 'uri'; + $fields[] = 'synctoken'; + $fields[] = 'components'; + $fields[] = 'principaluri'; + $fields[] = 'transparent'; + + // Making fields a comma-delimited list + $query = $this->db->getQueryBuilder(); + $query->select($fields)->from('calendars') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))) + ->orderBy('calendarorder', 'ASC'); + $stmt = $query->execute(); + + $calendars = []; + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + + $components = []; + if ($row['components']) { + $components = explode(',',$row['components']); + } + + $calendar = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'principaluri' => $row['principaluri'], + '{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'), + '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', + '{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components), + '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), + ]; + + foreach($this->propertyMap as $xmlName=>$dbName) { + $calendar[$xmlName] = $row[$dbName]; + } + + $calendars[] = $calendar; + } + + return $calendars; + } + + /** + * Creates a new calendar for a principal. + * + * If the creation was a success, an id must be returned that can be used to reference + * this calendar in other methods, such as updateCalendar. + * + * @param string $principalUri + * @param string $calendarUri + * @param array $properties + * @return void + */ + function createCalendar($principalUri, $calendarUri, array $properties) { + $fieldNames = [ + 'principaluri', + 'uri', + 'synctoken', + 'transparent', + 'components' + ]; + $values = [ + 'principaluri' => $principalUri, + 'uri' => $calendarUri, + 'synctoken' => 1, + 'transparent' => 0, + 'components' => 'VEVENT,VTODO' + ]; + + // Default value + $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'; + if (isset($properties[$sccs])) { + if (!($properties[$sccs] instanceof SupportedCalendarComponentSet)) { + throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Property\SupportedCalendarComponentSet'); + } + $values['components'] = implode(',',$properties[$sccs]->getValue()); + } + $transp = '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp'; + if (isset($properties[$transp])) { + $values['transparent'] = $properties[$transp]->getValue()==='transparent'; + } + + foreach($this->propertyMap as $xmlName=>$dbName) { + if (isset($properties[$xmlName])) { + + $values[$dbName] = $properties[$xmlName]; + $fieldNames[] = $dbName; + } + } + + $query = $this->db->getQueryBuilder(); + $query->insert('calendars') + ->values([ + 'principaluri' => $query->createNamedParameter($values['principaluri']), + 'uri' => $query->createNamedParameter($values['uri']), + 'synctoken' => $query->createNamedParameter($values['synctoken']), + 'transparent' => $query->createNamedParameter($values['transparent']), + ]) + ->execute(); + } + + /** + * Updates properties for a calendar. + * + * The list of mutations is stored in a Sabre\DAV\PropPatch object. + * To do the actual updates, you must tell this object which properties + * you're going to process with the handle() method. + * + * Calling the handle method is like telling the PropPatch object "I + * promise I can handle updating this property". + * + * Read the PropPatch documentation for more info and examples. + * + * @param string $path + * @param \Sabre\DAV\PropPatch $propPatch + * @return void + */ + function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { + $supportedProperties = array_keys($this->propertyMap); + $supportedProperties[] = '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp'; + + $propPatch->handle($supportedProperties, function($mutations) use ($calendarId) { + $newValues = []; + foreach ($mutations as $propertyName => $propertyValue) { + + switch ($propertyName) { + case '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' : + $fieldName = 'transparent'; + $newValues[$fieldName] = $propertyValue->getValue() === 'transparent'; + break; + default : + $fieldName = $this->propertyMap[$propertyName]; + $newValues[$fieldName] = $propertyValue; + break; + } + + } + $query = $this->db->getQueryBuilder(); + $query->update('calendars'); + foreach ($newValues as $fieldName => $value) { + $query->set($fieldName, $query->createNamedParameter($value)); + } + $query->where($query->expr()->eq('id', $query->createNamedParameter($calendarId))); + $query->execute(); + + $this->addChange($calendarId, "", 2); + + return true; + }); + } + + /** + * Delete a calendar and all it's objects + * + * @param mixed $calendarId + * @return void + */ + function deleteCalendar($calendarId) { + $stmt = $this->db->prepare('DELETE FROM `*PREFIX*calendarobjects` WHERE `calendarid` = ?'); + $stmt->execute([$calendarId]); + + $stmt = $this->db->prepare('DELETE FROM `*PREFIX*calendars` WHERE `id` = ?'); + $stmt->execute([$calendarId]); + + $stmt = $this->db->prepare('DELETE FROM `*PREFIX*calendarchanges` WHERE `calendarid` = ?'); + $stmt->execute([$calendarId]); + } + + /** + * Returns all calendar objects within a calendar. + * + * Every item contains an array with the following keys: + * * calendardata - The iCalendar-compatible calendar data + * * uri - a unique key which will be used to construct the uri. This can + * be any arbitrary string, but making sure it ends with '.ics' is a + * good idea. This is only the basename, or filename, not the full + * path. + * * lastmodified - a timestamp of the last modification time + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: + * '"abcdef"') + * * size - The size of the calendar objects, in bytes. + * * component - optional, a string containing the type of object, such + * as 'vevent' or 'vtodo'. If specified, this will be used to populate + * the Content-Type header. + * + * Note that the etag is optional, but it's highly encouraged to return for + * speed reasons. + * + * The calendardata is also optional. If it's not returned + * 'getCalendarObject' will be called later, which *is* expected to return + * calendardata. + * + * If neither etag or size are specified, the calendardata will be + * used/fetched to determine these numbers. If both are specified the + * amount of times this is needed is reduced by a great degree. + * + * @param mixed $calendarId + * @return array + */ + function getCalendarObjects($calendarId) { + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'componenttype']) + ->from('calendarobjects') + ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))); + $stmt = $query->execute(); + + $result = []; + foreach($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) { + $result[] = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'lastmodified' => $row['lastmodified'], + 'etag' => '"' . $row['etag'] . '"', + 'calendarid' => $row['calendarid'], + 'size' => (int)$row['size'], + 'component' => strtolower($row['componenttype']), + ]; + } + + return $result; + } + + /** + * Returns information from a single calendar object, based on it's object + * uri. + * + * The object uri is only the basename, or filename and not a full path. + * + * The returned array must have the same keys as getCalendarObjects. The + * 'calendardata' object is required here though, while it's not required + * for getCalendarObjects. + * + * This method must return null if the object did not exist. + * + * @param mixed $calendarId + * @param string $objectUri + * @return array|null + */ + function getCalendarObject($calendarId, $objectUri) { + + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype']) + ->from('calendarobjects') + ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))); + $stmt = $query->execute(); + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + + if(!$row) return null; + + return [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'lastmodified' => $row['lastmodified'], + 'etag' => '"' . $row['etag'] . '"', + 'calendarid' => $row['calendarid'], + 'size' => (int)$row['size'], + 'calendardata' => $this->readBlob($row['calendardata']), + 'component' => strtolower($row['componenttype']), + ]; + } + + /** + * Returns a list of calendar objects. + * + * This method should work identical to getCalendarObject, but instead + * return all the calendar objects in the list as an array. + * + * If the backend supports this, it may allow for some speed-ups. + * + * @param mixed $calendarId + * @param array $uris + * @return array + */ + function getMultipleCalendarObjects($calendarId, array $uris) { + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype']) + ->from('calendarobjects') + ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) + ->andWhere($query->expr()->in('uri', $query->createParameter('uri'))) + ->setParameter('uri', $uris, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY); + + $stmt = $query->execute(); + + $result = []; + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + + $result[] = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'lastmodified' => $row['lastmodified'], + 'etag' => '"' . $row['etag'] . '"', + 'calendarid' => $row['calendarid'], + 'size' => (int)$row['size'], + 'calendardata' => $this->readBlob($row['calendardata']), + 'component' => strtolower($row['componenttype']), + ]; + + } + return $result; + } + + /** + * Creates a new calendar object. + * + * The object uri is only the basename, or filename and not a full path. + * + * It is possible return an etag from this function, which will be used in + * the response to this PUT request. Note that the ETag must be surrounded + * by double-quotes. + * + * However, you should only really return this ETag if you don't mangle the + * calendar-data. If the result of a subsequent GET to this object is not + * the exact same as this request body, you should omit the ETag. + * + * @param mixed $calendarId + * @param string $objectUri + * @param string $calendarData + * @return string|null + */ + function createCalendarObject($calendarId, $objectUri, $calendarData) { + $extraData = $this->getDenormalizedData($calendarData); + + $query = $this->db->getQueryBuilder(); + $query->insert('calendarobjects') + ->values([ + 'calendarid' => $query->createNamedParameter($calendarId), + 'uri' => $query->createNamedParameter($objectUri), + 'calendardata' => $query->createNamedParameter($calendarData, \PDO::PARAM_LOB), + 'lastmodified' => $query->createNamedParameter(time()), + 'etag' => $query->createNamedParameter($extraData['etag']), + 'size' => $query->createNamedParameter($extraData['size']), + 'componenttype' => $query->createNamedParameter($extraData['componentType']), + 'firstoccurence' => $query->createNamedParameter($extraData['firstOccurence']), + 'lastoccurence' => $query->createNamedParameter($extraData['lastOccurence']), + 'uid' => $query->createNamedParameter($extraData['uid']), + ]) + ->execute(); + + $this->addChange($calendarId, $objectUri, 1); + + return '"' . $extraData['etag'] . '"'; + } + + /** + * Updates an existing calendarobject, based on it's uri. + * + * The object uri is only the basename, or filename and not a full path. + * + * It is possible return an etag from this function, which will be used in + * the response to this PUT request. Note that the ETag must be surrounded + * by double-quotes. + * + * However, you should only really return this ETag if you don't mangle the + * calendar-data. If the result of a subsequent GET to this object is not + * the exact same as this request body, you should omit the ETag. + * + * @param mixed $calendarId + * @param string $objectUri + * @param string $calendarData + * @return string|null + */ + function updateCalendarObject($calendarId, $objectUri, $calendarData) { + $extraData = $this->getDenormalizedData($calendarData); + + $query = $this->db->getQueryBuilder(); + $query->update('calendarobjects') + ->set('calendardata', $query->createNamedParameter($calendarData, \PDO::PARAM_LOB)) + ->set('lastmodified', $query->createNamedParameter(time())) + ->set('etag', $query->createNamedParameter($extraData['etag'])) + ->set('size', $query->createNamedParameter($extraData['size'])) + ->set('componenttype', $query->createNamedParameter($extraData['componentType'])) + ->set('firstoccurence', $query->createNamedParameter($extraData['firstOccurence'])) + ->set('lastoccurence', $query->createNamedParameter($extraData['lastOccurence'])) + ->set('uid', $query->createNamedParameter($extraData['uid'])) + ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))) + ->execute(); + + $this->addChange($calendarId, $objectUri, 2); + + return '"' . $extraData['etag'] . '"'; + } + + /** + * Deletes an existing calendar object. + * + * The object uri is only the basename, or filename and not a full path. + * + * @param mixed $calendarId + * @param string $objectUri + * @return void + */ + function deleteCalendarObject($calendarId, $objectUri) { + $stmt = $this->db->prepare('DELETE FROM `*PREFIX*calendarobjects` WHERE `calendarid` = ? AND `uri` = ?'); + $stmt->execute([$calendarId, $objectUri]); + + $this->addChange($calendarId, $objectUri, 3); + } + + /** + * Performs a calendar-query on the contents of this calendar. + * + * The calendar-query is defined in RFC4791 : CalDAV. Using the + * calendar-query it is possible for a client to request a specific set of + * object, based on contents of iCalendar properties, date-ranges and + * iCalendar component types (VTODO, VEVENT). + * + * This method should just return a list of (relative) urls that match this + * query. + * + * The list of filters are specified as an array. The exact array is + * documented by Sabre\CalDAV\CalendarQueryParser. + * + * Note that it is extremely likely that getCalendarObject for every path + * returned from this method will be called almost immediately after. You + * may want to anticipate this to speed up these requests. + * + * This method provides a default implementation, which parses *all* the + * iCalendar objects in the specified calendar. + * + * This default may well be good enough for personal use, and calendars + * that aren't very large. But if you anticipate high usage, big calendars + * or high loads, you are strongly adviced to optimize certain paths. + * + * The best way to do so is override this method and to optimize + * specifically for 'common filters'. + * + * Requests that are extremely common are: + * * requests for just VEVENTS + * * requests for just VTODO + * * requests with a time-range-filter on either VEVENT or VTODO. + * + * ..and combinations of these requests. It may not be worth it to try to + * handle every possible situation and just rely on the (relatively + * easy to use) CalendarQueryValidator to handle the rest. + * + * Note that especially time-range-filters may be difficult to parse. A + * time-range filter specified on a VEVENT must for instance also handle + * recurrence rules correctly. + * A good example of how to interprete all these filters can also simply + * be found in Sabre\CalDAV\CalendarQueryFilter. This class is as correct + * as possible, so it gives you a good idea on what type of stuff you need + * to think of. + * + * @param mixed $calendarId + * @param array $filters + * @return array + */ + function calendarQuery($calendarId, array $filters) { + $componentType = null; + $requirePostFilter = true; + $timeRange = null; + + // if no filters were specified, we don't need to filter after a query + if (!$filters['prop-filters'] && !$filters['comp-filters']) { + $requirePostFilter = false; + } + + // Figuring out if there's a component filter + if (count($filters['comp-filters']) > 0 && !$filters['comp-filters'][0]['is-not-defined']) { + $componentType = $filters['comp-filters'][0]['name']; + + // Checking if we need post-filters + if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['time-range'] && !$filters['comp-filters'][0]['prop-filters']) { + $requirePostFilter = false; + } + // There was a time-range filter + if ($componentType == 'VEVENT' && isset($filters['comp-filters'][0]['time-range'])) { + $timeRange = $filters['comp-filters'][0]['time-range']; + + // If start time OR the end time is not specified, we can do a + // 100% accurate mysql query. + if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['prop-filters'] && (!$timeRange['start'] || !$timeRange['end'])) { + $requirePostFilter = false; + } + } + + } + $columns = ['uri']; + if ($requirePostFilter) { + $columns = ['uri', 'calendardata']; + } + $query = $this->db->getQueryBuilder(); + $query->select($columns) + ->from('calendarobjects') + ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))); + + if ($componentType) { + $query->andWhere($query->expr()->eq('componenttype', $query->createNamedParameter($componentType))); + } + + if ($timeRange && $timeRange['start']) { + $query->andWhere($query->expr()->gt('lastoccurence', $query->createNamedParameter($timeRange['start']->getTimeStamp()))); + } + if ($timeRange && $timeRange['end']) { + $query->andWhere($query->expr()->lt('firstoccurence', $query->createNamedParameter($timeRange['end']->getTimeStamp()))); + } + + $stmt = $query->execute(); + + $result = []; + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + if ($requirePostFilter) { + if (!$this->validateFilterForObject($row, $filters)) { + continue; + } + } + $result[] = $row['uri']; + } + + return $result; + } + + /** + * Searches through all of a users calendars and calendar objects to find + * an object with a specific UID. + * + * This method should return the path to this object, relative to the + * calendar home, so this path usually only contains two parts: + * + * calendarpath/objectpath.ics + * + * If the uid is not found, return null. + * + * This method should only consider * objects that the principal owns, so + * any calendars owned by other principals that also appear in this + * collection should be ignored. + * + * @param string $principalUri + * @param string $uid + * @return string|null + */ + function getCalendarObjectByUID($principalUri, $uid) { + + $query = $this->db->getQueryBuilder(); + $query->select([$query->createFunction('c.`uri` AS `calendaruri`'), $query->createFunction('co.`uri` AS `objecturi`')]) + ->from('calendarobjects', 'co') + ->leftJoin('co', 'calendars', 'c', 'co.`calendarid` = c.`id`') + ->where($query->expr()->eq('c.principaluri', $query->createNamedParameter($principalUri))) + ->andWhere($query->expr()->eq('co.uid', $query->createNamedParameter($uid))); + + $stmt = $query->execute(); + + if ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + return $row['calendaruri'] . '/' . $row['objecturi']; + } + + return null; + } + + /** + * The getChanges method returns all the changes that have happened, since + * the specified syncToken in the specified calendar. + * + * This function should return an array, such as the following: + * + * [ + * 'syncToken' => 'The current synctoken', + * 'added' => [ + * 'new.txt', + * ], + * 'modified' => [ + * 'modified.txt', + * ], + * 'deleted' => [ + * 'foo.php.bak', + * 'old.txt' + * ] + * ); + * + * The returned syncToken property should reflect the *current* syncToken + * of the calendar, as reported in the {http://sabredav.org/ns}sync-token + * property This is * needed here too, to ensure the operation is atomic. + * + * If the $syncToken argument is specified as null, this is an initial + * sync, and all members should be reported. + * + * The modified property is an array of nodenames that have changed since + * the last token. + * + * The deleted property is an array with nodenames, that have been deleted + * from collection. + * + * The $syncLevel argument is basically the 'depth' of the report. If it's + * 1, you only have to report changes that happened only directly in + * immediate descendants. If it's 2, it should also include changes from + * the nodes below the child collections. (grandchildren) + * + * The $limit argument allows a client to specify how many results should + * be returned at most. If the limit is not specified, it should be treated + * as infinite. + * + * If the limit (infinite or not) is higher than you're willing to return, + * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception. + * + * If the syncToken is expired (due to data cleanup) or unknown, you must + * return null. + * + * The limit is 'suggestive'. You are free to ignore it. + * + * @param string $calendarId + * @param string $syncToken + * @param int $syncLevel + * @param int $limit + * @return array + */ + function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null) { + // Current synctoken + $stmt = $this->db->prepare('SELECT `synctoken` FROM `*PREFIX*calendars` WHERE `id` = ?'); + $stmt->execute([ $calendarId ]); + $currentToken = $stmt->fetchColumn(0); + + if (is_null($currentToken)) { + return null; + } + + $result = [ + 'syncToken' => $currentToken, + 'added' => [], + 'modified' => [], + 'deleted' => [], + ]; + + if ($syncToken) { + + $query = "SELECT `uri`, `operation` FROM `*PREFIX*calendarchanges` WHERE `synctoken` >= ? AND `synctoken` < ? AND `calendarid` = ? ORDER BY `synctoken`"; + if ($limit>0) { + $query.= " `LIMIT` " . (int)$limit; + } + + // Fetching all changes + $stmt = $this->db->prepare($query); + $stmt->execute([$syncToken, $currentToken, $calendarId]); + + $changes = []; + + // This loop ensures that any duplicates are overwritten, only the + // last change on a node is relevant. + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + + $changes[$row['uri']] = $row['operation']; + + } + + foreach($changes as $uri => $operation) { + + switch($operation) { + case 1 : + $result['added'][] = $uri; + break; + case 2 : + $result['modified'][] = $uri; + break; + case 3 : + $result['deleted'][] = $uri; + break; + } + + } + } else { + // No synctoken supplied, this is the initial sync. + $query = "SELECT `uri` FROM `*PREFIX*calendarobjects` WHERE `calendarid` = ?"; + $stmt = $this->db->prepare($query); + $stmt->execute([$calendarId]); + + $result['added'] = $stmt->fetchAll(\PDO::FETCH_COLUMN); + } + return $result; + + } + + /** + * Returns a list of subscriptions for a principal. + * + * Every subscription is an array with the following keys: + * * id, a unique id that will be used by other functions to modify the + * subscription. This can be the same as the uri or a database key. + * * uri. This is just the 'base uri' or 'filename' of the subscription. + * * principaluri. The owner of the subscription. Almost always the same as + * principalUri passed to this method. + * + * Furthermore, all the subscription info must be returned too: + * + * 1. {DAV:}displayname + * 2. {http://apple.com/ns/ical/}refreshrate + * 3. {http://calendarserver.org/ns/}subscribed-strip-todos (omit if todos + * should not be stripped). + * 4. {http://calendarserver.org/ns/}subscribed-strip-alarms (omit if alarms + * should not be stripped). + * 5. {http://calendarserver.org/ns/}subscribed-strip-attachments (omit if + * attachments should not be stripped). + * 6. {http://calendarserver.org/ns/}source (Must be a + * Sabre\DAV\Property\Href). + * 7. {http://apple.com/ns/ical/}calendar-color + * 8. {http://apple.com/ns/ical/}calendar-order + * 9. {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set + * (should just be an instance of + * Sabre\CalDAV\Property\SupportedCalendarComponentSet, with a bunch of + * default components). + * + * @param string $principalUri + * @return array + */ + function getSubscriptionsForUser($principalUri) { + $fields = array_values($this->subscriptionPropertyMap); + $fields[] = 'id'; + $fields[] = 'uri'; + $fields[] = 'source'; + $fields[] = 'principaluri'; + $fields[] = 'lastmodified'; + + $query = $this->db->getQueryBuilder(); + $query->select($fields) + ->from('calendarsubscriptions') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))) + ->orderBy('calendarorder', 'asc'); + $stmt =$query->execute(); + + $subscriptions = []; + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + + $subscription = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'principaluri' => $row['principaluri'], + 'source' => $row['source'], + 'lastmodified' => $row['lastmodified'], + + '{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VTODO', 'VEVENT']), + ]; + + foreach($this->subscriptionPropertyMap as $xmlName=>$dbName) { + if (!is_null($row[$dbName])) { + $subscription[$xmlName] = $row[$dbName]; + } + } + + $subscriptions[] = $subscription; + + } + + return $subscriptions; + } + + /** + * Creates a new subscription for a principal. + * + * If the creation was a success, an id must be returned that can be used to reference + * this subscription in other methods, such as updateSubscription. + * + * @param string $principalUri + * @param string $uri + * @param array $properties + * @return mixed + */ + function createSubscription($principalUri, $uri, array $properties) { + + if (!isset($properties['{http://calendarserver.org/ns/}source'])) { + throw new Forbidden('The {http://calendarserver.org/ns/}source property is required when creating subscriptions'); + } + + $values = [ + 'principaluri' => $principalUri, + 'uri' => $uri, + 'source' => $properties['{http://calendarserver.org/ns/}source']->getHref(), + 'lastmodified' => time(), + ]; + + foreach($this->subscriptionPropertyMap as $xmlName=>$dbName) { + if (isset($properties[$xmlName])) { + + $values[$dbName] = $properties[$xmlName]; + $fieldNames[] = $dbName; + } + } + + $query = $this->db->getQueryBuilder(); + $query->insert('calendarsubscriptions') + ->values([ + 'principaluri' => $query->createNamedParameter($values['principaluri']), + 'uri' => $query->createNamedParameter($values['uri']), + 'source' => $query->createNamedParameter($values['source']), + 'lastmodified' => $query->createNamedParameter($values['lastmodified']), + ]) + ->execute(); + + return $this->db->lastInsertId(); + } + + /** + * Updates a subscription + * + * The list of mutations is stored in a Sabre\DAV\PropPatch object. + * To do the actual updates, you must tell this object which properties + * you're going to process with the handle() method. + * + * Calling the handle method is like telling the PropPatch object "I + * promise I can handle updating this property". + * + * Read the PropPatch documentation for more info and examples. + * + * @param mixed $subscriptionId + * @param \Sabre\DAV\PropPatch $propPatch + * @return void + */ + function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) { + $supportedProperties = array_keys($this->subscriptionPropertyMap); + $supportedProperties[] = '{http://calendarserver.org/ns/}source'; + + $propPatch->handle($supportedProperties, function($mutations) use ($subscriptionId) { + + $newValues = []; + + foreach($mutations as $propertyName=>$propertyValue) { + if ($propertyName === '{http://calendarserver.org/ns/}source') { + $newValues['source'] = $propertyValue->getHref(); + } else { + $fieldName = $this->subscriptionPropertyMap[$propertyName]; + $newValues[$fieldName] = $propertyValue; + } + } + + $query = $this->db->getQueryBuilder(); + $query->update('calendarsubscriptions') + ->set('lastmodified', $query->createNamedParameter(time())); + foreach($newValues as $fieldName=>$value) { + $query->set($fieldName, $query->createNamedParameter($value)); + } + $query->where($query->expr()->eq('id', $query->createNamedParameter($subscriptionId))) + ->execute(); + + return true; + + }); + } + + /** + * Deletes a subscription. + * + * @param mixed $subscriptionId + * @return void + */ + function deleteSubscription($subscriptionId) { + $query = $this->db->getQueryBuilder(); + $query->delete('calendarsubscriptions') + ->where($query->expr()->eq('id', $query->createNamedParameter($subscriptionId))) + ->execute(); + } + + /** + * Returns a single scheduling object for the inbox collection. + * + * The returned array should contain the following elements: + * * uri - A unique basename for the object. This will be used to + * construct a full uri. + * * calendardata - The iCalendar object + * * lastmodified - The last modification date. Can be an int for a unix + * timestamp, or a PHP DateTime object. + * * etag - A unique token that must change if the object changed. + * * size - The size of the object, in bytes. + * + * @param string $principalUri + * @param string $objectUri + * @return array + */ + function getSchedulingObject($principalUri, $objectUri) { + // TODO: Implement getSchedulingObject() method. + } + + /** + * Returns all scheduling objects for the inbox collection. + * + * These objects should be returned as an array. Every item in the array + * should follow the same structure as returned from getSchedulingObject. + * + * The main difference is that 'calendardata' is optional. + * + * @param string $principalUri + * @return array + */ + function getSchedulingObjects($principalUri) { + // TODO: Implement getSchedulingObjects() method. + } + + /** + * Deletes a scheduling object from the inbox collection. + * + * @param string $principalUri + * @param string $objectUri + * @return void + */ + function deleteSchedulingObject($principalUri, $objectUri) { + // TODO: Implement deleteSchedulingObject() method. + } + + /** + * Creates a new scheduling object. This should land in a users' inbox. + * + * @param string $principalUri + * @param string $objectUri + * @param string $objectData + * @return void + */ + function createSchedulingObject($principalUri, $objectUri, $objectData) { + // TODO: Implement createSchedulingObject() method. + } + + /** + * Adds a change record to the calendarchanges table. + * + * @param mixed $calendarId + * @param string $objectUri + * @param int $operation 1 = add, 2 = modify, 3 = delete. + * @return void + */ + protected function addChange($calendarId, $objectUri, $operation) { + + $stmt = $this->db->prepare('INSERT INTO `*PREFIX*calendarchanges` (`uri`, `synctoken`, `calendarid`, `operation`) SELECT ?, `synctoken`, ?, ? FROM `*PREFIX*calendars` WHERE `id` = ?'); + $stmt->execute([ + $objectUri, + $calendarId, + $operation, + $calendarId + ]); + $stmt = $this->db->prepare('UPDATE `*PREFIX*calendars` SET `synctoken` = `synctoken` + 1 WHERE `id` = ?'); + $stmt->execute([ + $calendarId + ]); + + } + + /** + * Parses some information from calendar objects, used for optimized + * calendar-queries. + * + * Returns an array with the following keys: + * * etag - An md5 checksum of the object without the quotes. + * * size - Size of the object in bytes + * * componentType - VEVENT, VTODO or VJOURNAL + * * firstOccurence + * * lastOccurence + * * uid - value of the UID property + * + * @param string $calendarData + * @return array + */ + protected function getDenormalizedData($calendarData) { + + $vObject = Reader::read($calendarData); + $componentType = null; + $component = null; + $firstOccurence = null; + $lastOccurence = null; + $uid = null; + foreach($vObject->getComponents() as $component) { + if ($component->name!=='VTIMEZONE') { + $componentType = $component->name; + $uid = (string)$component->UID; + break; + } + } + if (!$componentType) { + throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); + } + if ($componentType === 'VEVENT') { + $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp(); + // Finding the last occurence is a bit harder + if (!isset($component->RRULE)) { + if (isset($component->DTEND)) { + $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp(); + } elseif (isset($component->DURATION)) { + $endDate = clone $component->DTSTART->getDateTime(); + $endDate->add(DateTimeParser::parse($component->DURATION->getValue())); + $lastOccurence = $endDate->getTimeStamp(); + } elseif (!$component->DTSTART->hasTime()) { + $endDate = clone $component->DTSTART->getDateTime(); + $endDate->modify('+1 day'); + $lastOccurence = $endDate->getTimeStamp(); + } else { + $lastOccurence = $firstOccurence; + } + } else { + $it = new RecurrenceIterator($vObject, (string)$component->UID); + $maxDate = new \DateTime(self::MAX_DATE); + if ($it->isInfinite()) { + $lastOccurence = $maxDate->getTimeStamp(); + } else { + $end = $it->getDtEnd(); + while($it->valid() && $end < $maxDate) { + $end = $it->getDtEnd(); + $it->next(); + + } + $lastOccurence = $end->getTimeStamp(); + } + + } + } + + return [ + 'etag' => md5($calendarData), + 'size' => strlen($calendarData), + 'componentType' => $componentType, + 'firstOccurence' => $firstOccurence, + 'lastOccurence' => $lastOccurence, + 'uid' => $uid, + ]; + + } + + private function readBlob($cardData) { + if (is_resource($cardData)) { + return stream_get_contents($cardData); + } + + return $cardData; + } +} diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php index 850180d8481..10baff072cc 100644 --- a/apps/dav/lib/rootcollection.php +++ b/apps/dav/lib/rootcollection.php @@ -2,8 +2,10 @@ namespace OCA\DAV; +use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\Connector\Sabre\Principal; +use Sabre\CalDAV\CalendarRoot; use Sabre\CalDAV\Principal\Collection; use Sabre\CardDAV\AddressBookRoot; use Sabre\DAV\SimpleCollection; @@ -12,9 +14,10 @@ class RootCollection extends SimpleCollection { public function __construct() { $config = \OC::$server->getConfig(); + $db = \OC::$server->getDatabaseConnection(); $principalBackend = new Principal( - $config, - \OC::$server->getUserManager() + $config, + \OC::$server->getUserManager() ); // as soon as debug mode is enabled we allow listing of principals $disableListing = !$config->getSystemValue('debug', false); @@ -24,14 +27,18 @@ class RootCollection extends SimpleCollection { $principalCollection->disableListing = $disableListing; $filesCollection = new Files\RootCollection($principalBackend); $filesCollection->disableListing = $disableListing; - $cardDavBackend = new CardDavBackend(\OC::$server->getDatabaseConnection()); + $caldavBackend = new CalDavBackend($db); + $calendarRoot = new CalendarRoot($principalBackend, $caldavBackend); + $calendarRoot->disableListing = $disableListing; + $cardDavBackend = new CardDavBackend($db); $addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend); $addressBookRoot->disableListing = $disableListing; $children = [ - $principalCollection, - $filesCollection, - $addressBookRoot, + $principalCollection, + $filesCollection, + $calendarRoot, + $addressBookRoot, ]; parent::__construct('root', $children); diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index a92c9980f54..27a087581d7 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -33,8 +33,18 @@ class Server { $this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig())); $this->server->addPlugin(new Plugin($authBackend, 'ownCloud')); + // calendar plugins + $this->server->addPlugin(new \Sabre\CalDAV\Plugin()); $this->server->addPlugin(new \Sabre\DAVACL\Plugin()); + $this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); + $senderEmail = \OCP\Util::getDefaultEmailAddress('no-reply'); + $this->server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); + $this->server->addPlugin(new \Sabre\CalDAV\Schedule\IMipPlugin($senderEmail)); + $this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); + $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); + $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); + // addressbook plugins $this->server->addPlugin(new \Sabre\CardDAV\Plugin()); // wait with registering these until auth is handled and the filesystem is setup diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php new file mode 100644 index 00000000000..beb88a398b9 --- /dev/null +++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php @@ -0,0 +1,325 @@ + + * + * @copyright Copyright (c) 2015, 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 Tests\Connector\Sabre; + +use DateTime; +use DateTimeZone; +use OCA\DAV\CalDAV\CalDavBackend; +use Sabre\DAV\Property\Href; +use Sabre\DAV\PropPatch; +use Test\TestCase; + +/** + * Class CalDavBackendTest + * + * @group DB + * + * @package Tests\Connector\Sabre + */ +class CalDavBackendTest extends TestCase { + + /** @var CalDavBackend */ + private $backend; + + const UNIT_TEST_USER = 'caldav-unit-test'; + + + public function setUp() { + parent::setUp(); + + $db = \OC::$server->getDatabaseConnection(); + $this->backend = new CalDavBackend($db); + + $this->tearDown(); + } + + public function tearDown() { + parent::tearDown(); + + if (is_null($this->backend)) { + return; + } + $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); + foreach ($books as $book) { + $this->backend->deleteCalendar($book['id']); + } + $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); + foreach ($subscriptions as $subscription) { + $this->backend->deleteSubscription($subscription['id']); + } + } + + public function testCalendarOperations() { + + $calendarId = $this->createTestCalendar(); + + // update it's display name + $patch = new PropPatch([ + '{DAV:}displayname' => 'Unit test', + '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar used for unit testing' + ]); + $this->backend->updateCalendar($calendarId, $patch); + $patch->commit(); + $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $this->assertEquals('Unit test', $books[0]['{DAV:}displayname']); + $this->assertEquals('Calendar used for unit testing', $books[0]['{urn:ietf:params:xml:ns:caldav}calendar-description']); + + // delete the address book + $this->backend->deleteCalendar($books[0]['id']); + $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); + $this->assertEquals(0, count($books)); + } + + public function testCalendarObjectsOperations() { + + $calendarId = $this->createTestCalendar(); + + // create a card + $uri = $this->getUniqueID('calobj'); + $calData = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + + $this->backend->createCalendarObject($calendarId, $uri, $calData); + + // get all the cards + $calendarObjects = $this->backend->getCalendarObjects($calendarId); + $this->assertEquals(1, count($calendarObjects)); + $this->assertEquals($calendarId, $calendarObjects[0]['calendarid']); + + // get the cards + $calendarObject = $this->backend->getCalendarObject($calendarId, $uri); + $this->assertNotNull($calendarObject); + $this->assertArrayHasKey('id', $calendarObject); + $this->assertArrayHasKey('uri', $calendarObject); + $this->assertArrayHasKey('lastmodified', $calendarObject); + $this->assertArrayHasKey('etag', $calendarObject); + $this->assertArrayHasKey('size', $calendarObject); + $this->assertEquals($calData, $calendarObject['calendardata']); + + // update the card + $calData = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +END:VEVENT +END:VCALENDAR +EOD; + $this->backend->updateCalendarObject($calendarId, $uri, $calData); + $calendarObject = $this->backend->getCalendarObject($calendarId, $uri); + $this->assertEquals($calData, $calendarObject['calendardata']); + + // delete the card + $this->backend->deleteCalendarObject($calendarId, $uri); + $calendarObjects = $this->backend->getCalendarObjects($calendarId); + $this->assertEquals(0, count($calendarObjects)); + } + + public function testMultiCalendarObjects() { + + $calendarId = $this->createTestCalendar(); + + // create an event + $calData = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + $uri0 = $this->getUniqueID('card'); + $this->backend->createCalendarObject($calendarId, $uri0, $calData); + $uri1 = $this->getUniqueID('card'); + $this->backend->createCalendarObject($calendarId, $uri1, $calData); + $uri2 = $this->getUniqueID('card'); + $this->backend->createCalendarObject($calendarId, $uri2, $calData); + + // get all the cards + $calendarObjects = $this->backend->getCalendarObjects($calendarId); + $this->assertEquals(3, count($calendarObjects)); + + // get the cards + $calendarObjects = $this->backend->getMultipleCalendarObjects($calendarId, [$uri1, $uri2]); + $this->assertEquals(2, count($calendarObjects)); + foreach($calendarObjects as $card) { + $this->assertArrayHasKey('id', $card); + $this->assertArrayHasKey('uri', $card); + $this->assertArrayHasKey('lastmodified', $card); + $this->assertArrayHasKey('etag', $card); + $this->assertArrayHasKey('size', $card); + $this->assertEquals($calData, $card['calendardata']); + } + + // delete the card + $this->backend->deleteCalendarObject($calendarId, $uri0); + $this->backend->deleteCalendarObject($calendarId, $uri1); + $this->backend->deleteCalendarObject($calendarId, $uri2); + $calendarObjects = $this->backend->getCalendarObjects($calendarId); + $this->assertEquals(0, count($calendarObjects)); + } + + /** + * @dataProvider providesCalendarQueryParameters + */ + public function testCalendarQuery($expectedEventsInResult, $propFilters, $compFilter) { + $calendarId = $this->createTestCalendar(); + $events = []; + $events[0] = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); + $events[1] = $this->createEvent($calendarId, '20130912T150000Z', '20130912T170000Z'); + $events[2] = $this->createEvent($calendarId, '20130912T173000Z', '20130912T220000Z'); + + $result = $this->backend->calendarQuery($calendarId, [ + 'name' => '', + 'prop-filters' => $propFilters, + 'comp-filters' => $compFilter + ]); + + $expectedEventsInResult = array_map(function($index) use($events) { + return $events[$index]; + }, $expectedEventsInResult); + $this->assertEquals($expectedEventsInResult, $result, '', 0.0, 10, true); + } + + public function testGetCalendarObjectByUID() { + $calendarId = $this->createTestCalendar(); + $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); + + $co = $this->backend->getCalendarObjectByUID(self::UNIT_TEST_USER, '47d15e3ec8'); + $this->assertNotNull($co); + } + + public function providesCalendarQueryParameters() { + return [ + 'all' => [[0, 1, 2], [], []], + 'only-todos' => [[], ['name' => 'VTODO'], []], + 'only-events' => [[0, 1, 2], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => null], 'prop-filters' => []]],], + 'start' => [[1, 2], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],], + 'end' => [[0], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC'))], 'prop-filters' => []]],], + ]; + } + + private function createTestCalendar() { + $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []); + $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($calendars)); + $this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']); + $this->assertEquals('Example', $calendars[0]['uri']); + $calendarId = $calendars[0]['id']; + + return $calendarId; + } + + private function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') { + + $calData = <<getUniqueID('event'); + $this->backend->createCalendarObject($calendarId, $uri0, $calData); + + return $uri0; + } + + public function testSyncSupport() { + $calendarId = $this->createTestCalendar(); + + // fist call without synctoken + $changes = $this->backend->getChangesForCalendar($calendarId, '', 1); + $syncToken = $changes['syncToken']; + + // add a change + $event = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); + + // look for changes + $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1); + $this->assertEquals($event, $changes['added'][0]); + } + + public function testSubscriptions() { + $id = $this->backend->createSubscription(self::UNIT_TEST_USER, 'Subscription', [ + '{http://calendarserver.org/ns/}source' => new Href('test-source') + ]); + + $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($subscriptions)); + $this->assertEquals($id, $subscriptions[0]['id']); + + $patch = new PropPatch([ + '{DAV:}displayname' => 'Unit test', + ]); + $this->backend->updateSubscription($id, $patch); + $patch->commit(); + + $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($subscriptions)); + $this->assertEquals($id, $subscriptions[0]['id']); + $this->assertEquals('Unit test', $subscriptions[0]['{DAV:}displayname']); + + $this->backend->deleteSubscription($id); + $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); + $this->assertEquals(0, count($subscriptions)); + } + +} -- GitLab From 1e9fc332125aa8e730c3cdccd88102cfcd6bce9d Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 6 Nov 2015 12:05:19 +0100 Subject: [PATCH 035/344] [Share2.0] OCS Share API getShare uses new code --- apps/files_sharing/api/ocssharewrapper.php | 14 +- apps/files_sharing/api/share20ocs.php | 100 ++++++- .../tests/api/share20ocstest.php | 259 +++++++++++++++++- lib/private/share20/defaultshareprovider.php | 9 +- lib/private/share20/ishare.php | 21 ++ lib/private/share20/share.php | 57 +++- .../lib/share20/defaultshareprovidertest.php | 2 +- 7 files changed, 418 insertions(+), 44 deletions(-) diff --git a/apps/files_sharing/api/ocssharewrapper.php b/apps/files_sharing/api/ocssharewrapper.php index 8c0d8f7d150..3ce2901dfb4 100644 --- a/apps/files_sharing/api/ocssharewrapper.php +++ b/apps/files_sharing/api/ocssharewrapper.php @@ -35,15 +35,16 @@ class OCSShareWrapper { \OC::$server->getUserFolder(), new \OC\Share20\DefaultShareProvider( \OC::$server->getDatabaseConnection(), - \OC::$server->getUserManager(), - \OC::$server->getGroupManager(), - \OC::$server->getUserFolder() + \OC::$server->getUserManager(), + \OC::$server->getGroupManager(), + \OC::$server->getUserFolder() ) ), \OC::$server->getGroupManager(), \OC::$server->getUserManager(), \OC::$server->getRequest(), - \OC::$server->getUserFolder()); + \OC::$server->getUserFolder(), + \OC::$server->getURLGenerator()); } public function getAllShares($params) { @@ -55,7 +56,8 @@ class OCSShareWrapper { } public function getShare($params) { - return \OCA\Files_Sharing\API\Local::getShare($params); + $id = $params['id']; + return $this->getShare20OCS()->getShare($id); } public function updateShare($params) { @@ -63,7 +65,7 @@ class OCSShareWrapper { } public function deleteShare($params) { - $id = (int)$params['id']; + $id = $params['id']; return $this->getShare20OCS()->deleteShare($id); } } diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php index 8a7f90c0023..aaf5a3c72b6 100644 --- a/apps/files_sharing/api/share20ocs.php +++ b/apps/files_sharing/api/share20ocs.php @@ -20,39 +20,125 @@ */ namespace OCA\Files_Sharing\API; +use OC\Share20\IShare; + class Share20OCS { - /** @var OC\Share20\Manager */ + /** @var \OC\Share20\Manager */ private $shareManager; - /** @var OCP\IGroupManager */ + /** @var \OCP\IGroupManager */ private $groupManager; - /** @var OCP\IUserManager */ + /** @var \OCP\IUserManager */ private $userManager; - /** @var OCP\IRequest */ + /** @var \OCP\IRequest */ private $request; - /** @var OCP\Files\Folder */ + /** @var \OCP\Files\Folder */ private $userFolder; public function __construct(\OC\Share20\Manager $shareManager, \OCP\IGroupManager $groupManager, \OCP\IUserManager $userManager, \OCP\IRequest $request, - \OCP\Files\Folder $userFolder) { + \OCP\Files\Folder $userFolder, + \OCP\IURLGenerator $urlGenerator) { $this->shareManager = $shareManager; $this->userManager = $userManager; $this->groupManager = $groupManager; $this->request = $request; $this->userFolder = $userFolder; + $this->urlGenerator = $urlGenerator; + } + + /** + * Convert an IShare to an array for OCS output + * + * @param IShare $share + * @return array + */ + protected function formatShare($share) { + $result = [ + 'id' => $share->getId(), + 'share_type' => $share->getShareType(), + 'uid_owner' => $share->getSharedBy()->getUID(), + 'displayname_owner' => $share->getSharedBy()->getDisplayName(), + 'permissions' => $share->getPermissions(), + 'stime' => $share->getShareTime(), + 'parent' => $share->getParent(), + 'expiration' => null, + 'token' => null, + ]; + + $path = $share->getPath(); + $result['path'] = $this->userFolder->getRelativePath($path->getPath()); + if ($path instanceOf \OCP\Files\Folder) { + $result['item_type'] = 'folder'; + } else { + $result['item_type'] = 'file'; + } + $result['storage_id'] = $path->getStorage()->getId(); + $result['storage'] = \OC\Files\Cache\Storage::getNumericStorageId($path->getStorage()->getId()); + $result['item_source'] = $path->getId(); + $result['file_source'] = $path->getId(); + $result['file_parent'] = $path->getParent()->getId(); + $result['file_target'] = $share->getTarget(); + + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + $sharedWith = $share->getSharedWith(); + $result['share_with'] = $sharedWith->getUID(); + $result['share_with_displayname'] = $sharedWith->getDisplayName(); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $sharedWith = $share->getSharedWith(); + $result['share_with'] = $sharedWith->getGID(); + $result['share_with_displayname'] = $sharedWith->getGID(); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + + $result['share_with'] = $share->getPassword(); + $result['share_with_displayname'] = $share->getPassword(); + + $result['token'] = $share->getToken(); + $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); + + $expiration = $share->getExpirationDate(); + if ($expiration !== null) { + $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); + } + + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = $share->getSharedWith(); + $result['token'] = $share->getToken(); + } + + $result['mail_send'] = $share->getMailSend() ? 1 : 0; + + return $result; + } + + /** + * Get a specific share by id + * + * @param string $id + * @return \OC_OCS_Result + */ + public function getShare($id) { + try { + $share = $this->shareManager->getShareById($id); + } catch (\OC\Share20\Exception\ShareNotFound $e) { + return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.'); + } + + $share = $this->formatShare($share); + return new \OC_OCS_Result($share); } /** * Delete a share * - * @param int $id + * @param string $id * @return \OC_OCS_Result */ public function deleteShare($id) { diff --git a/apps/files_sharing/tests/api/share20ocstest.php b/apps/files_sharing/tests/api/share20ocstest.php index 9c4377a2a7f..f74585eb47d 100644 --- a/apps/files_sharing/tests/api/share20ocstest.php +++ b/apps/files_sharing/tests/api/share20ocstest.php @@ -39,6 +39,9 @@ class Share20OCSTest extends \Test\TestCase { /** @var OCP\Files\Folder */ private $userFolder; + /** @var OCP\IURLGenerator */ + private $urlGenerator; + /** @var OCS */ private $ocs; @@ -46,24 +49,18 @@ class Share20OCSTest extends \Test\TestCase { $this->shareManager = $this->getMockBuilder('OC\Share20\Manager') ->disableOriginalConstructor() ->getMock(); - $this->groupManager = $this->getMockBuilder('OCP\IGroupManager') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager = $this->getMockBuilder('OCP\IUserManager') - ->disableOriginalConstructor() - ->getMock(); - $this->request = $this->getMockBuilder('OCP\IRequest') - ->disableOriginalConstructor() - ->getMock(); - $this->userFolder = $this->getMockBuilder('OCP\Files\Folder') - ->disableOriginalConstructor() - ->getMock(); + $this->groupManager = $this->getMock('OCP\IGroupManager'); + $this->userManager = $this->getMock('OCP\IUserManager'); + $this->request = $this->getMock('OCP\IRequest'); + $this->userFolder = $this->getMock('OCP\Files\Folder'); + $this->urlGenerator = $this->getMock('OCP\IURLGenerator'); $this->ocs = new Share20OCS($this->shareManager, $this->groupManager, $this->userManager, $this->request, - $this->userFolder); + $this->userFolder, + $this->urlGenerator); } public function testDeleteShareShareNotFound() { @@ -110,4 +107,240 @@ class Share20OCSTest extends \Test\TestCase { $expected = new \OC_OCS_Result(); $this->assertEquals($expected, $this->ocs->deleteShare(42)); } + + public function testGetGetShareNotExists() { + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with(42) + ->will($this->throwException(new \OC\Share20\Exception\ShareNotFound())); + + $expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.'); + $this->assertEquals($expected, $this->ocs->getShare(42)); + } + + public function createShare($id, $shareType, $sharedWith, $sharedBy, $path, $permissions, + $shareTime, $expiration, $parent, $target, $mail_send, $token=null, + $password=null) { + $share = $this->getMock('OC\Share20\IShare'); + $share->method('getId')->willReturn($id); + $share->method('getShareType')->willReturn($shareType); + $share->method('getSharedWith')->willReturn($sharedWith); + $share->method('getSharedBy')->willReturn($sharedBy); + $share->method('getPath')->willReturn($path); + $share->method('getPermissions')->willReturn($permissions); + $share->method('getShareTime')->willReturn($shareTime); + $share->method('getExpirationDate')->willReturn($expiration); + $share->method('getParent')->willReturn($parent); + $share->method('getTarget')->willReturn($target); + $share->method('getMailSend')->willReturn($mail_send); + $share->method('getToken')->willReturn($token); + $share->method('getPassword')->willReturn($password); + + return $share; + } + + public function dataGetShare() { + $data = []; + + $owner = $this->getMock('OCP\IUser'); + $owner->method('getUID')->willReturn('ownerId'); + $owner->method('getDisplayName')->willReturn('ownerDisplay'); + + $user = $this->getMock('OCP\IUser'); + $user->method('getUID')->willReturn('userId'); + $user->method('getDisplayName')->willReturn('userDisplay'); + + $group = $this->getMock('OCP\IGroup'); + $group->method('getGID')->willReturn('groupId'); + + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('getId')->willReturn('STORAGE'); + + $parentFolder = $this->getMock('OCP\Files\Folder'); + $parentFolder->method('getId')->willReturn(3); + + $file = $this->getMock('OCP\Files\File'); + $file->method('getId')->willReturn(1); + $file->method('getPath')->willReturn('file'); + $file->method('getStorage')->willReturn($storage); + $file->method('getParent')->willReturn($parentFolder); + + $folder = $this->getMock('OCP\Files\Folder'); + $folder->method('getId')->willReturn(2); + $folder->method('getPath')->willReturn('folder'); + $folder->method('getStorage')->willReturn($storage); + $folder->method('getParent')->willReturn($parentFolder); + + // File shared with user + $share = $this->createShare(100, + \OCP\Share::SHARE_TYPE_USER, + $user, + $owner, + $file, + 4, + 5, + null, + 6, + 'target', + 0); + $expected = [ + 'id' => 100, + 'share_type' => \OCP\Share::SHARE_TYPE_USER, + 'share_with' => 'userId', + 'share_with_displayname' => 'userDisplay', + 'uid_owner' => 'ownerId', + 'displayname_owner' => 'ownerDisplay', + 'item_type' => 'file', + 'item_source' => 1, + 'file_source' => 1, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => null, + 'expiration' => null, + 'permissions' => 4, + 'stime' => 5, + 'parent' => 6, + 'storage_id' => 'STORAGE', + 'path' => 'file', + 'storage' => null, // HACK around static function + 'mail_send' => 0, + ]; + $data[] = [$share, $expected]; + + // Folder shared with group + $share = $this->createShare(101, + \OCP\Share::SHARE_TYPE_GROUP, + $group, + $owner, + $folder, + 4, + 5, + null, + 6, + 'target', + 0); + $expected = [ + 'id' => 101, + 'share_type' => \OCP\Share::SHARE_TYPE_GROUP, + 'share_with' => 'groupId', + 'share_with_displayname' => 'groupId', + 'uid_owner' => 'ownerId', + 'displayname_owner' => 'ownerDisplay', + 'item_type' => 'folder', + 'item_source' => 2, + 'file_source' => 2, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => null, + 'expiration' => null, + 'permissions' => 4, + 'stime' => 5, + 'parent' => 6, + 'storage_id' => 'STORAGE', + 'path' => 'folder', + 'storage' => null, // HACK around static function + 'mail_send' => 0, + ]; + $data[] = [$share, $expected]; + + // Folder shared with remote + $share = $this->createShare(101, + \OCP\Share::SHARE_TYPE_REMOTE, + 'user@remote.com', + $owner, + $folder, + 4, + 5, + null, + 6, + 'target', + 0); + $expected = [ + 'id' => 101, + 'share_type' => \OCP\Share::SHARE_TYPE_REMOTE, + 'share_with' => 'user@remote.com', + 'share_with_displayname' => 'user@remote.com', + 'uid_owner' => 'ownerId', + 'displayname_owner' => 'ownerDisplay', + 'item_type' => 'folder', + 'item_source' => 2, + 'file_source' => 2, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => null, + 'expiration' => null, + 'permissions' => 4, + 'stime' => 5, + 'parent' => 6, + 'storage_id' => 'STORAGE', + 'path' => 'folder', + 'storage' => null, // HACK around static function + 'mail_send' => 0, + ]; + $data[] = [$share, $expected]; + + // File shared by link with Expire + $expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03'); + $share = $this->createShare(101, + \OCP\Share::SHARE_TYPE_LINK, + null, + $owner, + $folder, + 4, + 5, + $expire, + 6, + 'target', + 0, + 'token', + 'password'); + $expected = [ + 'id' => 101, + 'share_type' => \OCP\Share::SHARE_TYPE_LINK, + 'share_with' => 'password', + 'share_with_displayname' => 'password', + 'uid_owner' => 'ownerId', + 'displayname_owner' => 'ownerDisplay', + 'item_type' => 'folder', + 'item_source' => 2, + 'file_source' => 2, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => 'token', + 'expiration' => '2000-01-02 00:00:00', + 'permissions' => 4, + 'stime' => 5, + 'parent' => 6, + 'storage_id' => 'STORAGE', + 'path' => 'folder', + 'storage' => null, // HACK around static function + 'mail_send' => 0, + 'url' => 'url', + ]; + $data[] = [$share, $expected]; + + return $data; + } + + /** + * @dataProvider dataGetShare + */ + public function testGetShare(\OC\Share20\IShare $share, array $result) { + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with($share->getId()) + ->willReturn($share); + + $this->userFolder + ->method('getRelativePath') + ->will($this->returnArgument(0)); + + $this->urlGenerator + ->method('linkToRouteAbsolute') + ->willReturn('url'); + + $expected = new \OC_OCS_Result($result); + $this->assertEquals($expected->getData(), $this->ocs->getShare($share->getId())->getData()); } } diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php index 79bc809b9b2..7f21d3aadf5 100644 --- a/lib/private/share20/defaultshareprovider.php +++ b/lib/private/share20/defaultshareprovider.php @@ -235,17 +235,16 @@ class DefaultShareProvider implements IShareProvider { $share->setId((int)$data['id']) ->setShareType((int)$data['share_type']) ->setPermissions((int)$data['permissions']) - ->setTarget($data['file_target']); + ->setTarget($data['file_target']) + ->setShareTime((int)$data['stime']) + ->setMailSend((bool)$data['mail_send']); if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { $share->setSharedWith($this->userManager->get($data['share_with'])); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $share->setSharedWith($this->groupManager->get($data['share_with'])); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { - /* - * TODO: Clean this up, this should be set as password not sharedWith - */ - $share->setSharedWith($data['share_with']); + $share->setPassword($data['share_with']); $share->setToken($data['token']); } else { $share->setSharedWith($data['share_with']); diff --git a/lib/private/share20/ishare.php b/lib/private/share20/ishare.php index fa7c1ea614c..a80abebd71c 100644 --- a/lib/private/share20/ishare.php +++ b/lib/private/share20/ishare.php @@ -133,6 +133,13 @@ interface IShare { */ public function setPassword($password); + /** + * Is a password set for this share + * + * @return string + */ + public function getPassword(); + /** * Get the token * @@ -153,4 +160,18 @@ interface IShare { * @return string */ public function getTarget(); + + /** + * Get the timestamp this share was created + * + * @return int + */ + public function getSharetime(); + + /** + * Get mailSend + * + * @return bool + */ + public function getMailSend(); } diff --git a/lib/private/share20/share.php b/lib/private/share20/share.php index 989edd3c079..4200816799e 100644 --- a/lib/private/share20/share.php +++ b/lib/private/share20/share.php @@ -28,39 +28,32 @@ class Share implements IShare { /** @var string */ private $id; - /** @var Node */ private $path; - /** @var int */ private $shareType; - /** @var IUser|IGroup|string */ private $sharedWith; - /** @var IUser|string */ private $sharedBy; - /** @var IUser|string */ private $shareOwner; - /** @var int */ private $permissions; - /** @var \DateTime */ private $expireDate; - /** @var string */ private $password; - /** @var string */ private $token; - /** @var int */ private $parent; - /** @var string */ private $target; + /** @var int */ + private $shareTime; + /** @var bool */ + private $mailSend; /** * Set the id of the share @@ -252,7 +245,7 @@ class Share implements IShare { * * @return string */ - public function getPassword($password) { + public function getPassword() { return $this->password; } @@ -315,4 +308,44 @@ class Share implements IShare { public function getTarget() { return $this->target; } + + /** + * Set the time this share was created + * + * @param int $shareTime + * @return Share The modified object + */ + public function setShareTime($shareTime) { + $this->shareTime = $shareTime; + return $this; + } + + /** + * Get the timestamp this share was created + * + * @return int + */ + public function getSharetime() { + return $this->shareTime; + } + + /** + * Set mailSend + * + * @param bool $mailSend + * @return Share The modified object + */ + public function setMailSend($mailSend) { + $this->mailSend = $mailSend; + return $this; + } + + /** + * Get mailSend + * + * @return bool + */ + public function getMailSend() { + return $this->mailSend; + } } diff --git a/tests/lib/share20/defaultshareprovidertest.php b/tests/lib/share20/defaultshareprovidertest.php index e99290f6724..f8b6f98be7c 100644 --- a/tests/lib/share20/defaultshareprovidertest.php +++ b/tests/lib/share20/defaultshareprovidertest.php @@ -266,7 +266,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals($id, $share->getId()); $this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType()); - $this->assertEquals('sharedWith', $share->getSharedWith()); + $this->assertEquals('sharedWith', $share->getPassword()); $this->assertEquals($sharedBy, $share->getSharedBy()); $this->assertEquals($shareOwner, $share->getShareOwner()); $this->assertEquals($path, $share->getPath()); -- GitLab From 78c456b8958e15d10109e2cf4a6fea99d4b7ea46 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 16 Nov 2015 14:21:45 +0100 Subject: [PATCH 036/344] Allow creating OCS v2 links in JS --- core/js/js.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/js/js.js b/core/js/js.js index 07320a1d225..57c9871233b 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -119,10 +119,12 @@ var OC={ /** * Gets the base path for the given OCS API service. * @param {string} service name + * @param {int} version OCS API version * @return {string} OCS API base path */ - linkToOCS: function(service) { - return window.location.protocol + '//' + window.location.host + OC.webroot + '/ocs/v1.php/' + service + '/'; + linkToOCS: function(service, version) { + version = (version !== 2) ? 1 : 2; + return window.location.protocol + '//' + window.location.host + OC.webroot + '/ocs/v' + version + '.php/' + service + '/'; }, /** -- GitLab From 61425b7621973faadafe070175e51278acb2e159 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 6 Nov 2015 14:54:31 +0100 Subject: [PATCH 037/344] Moved grouptest over to pure unit tests --- apps/provisioning_api/appinfo/routes.php | 3 +- apps/provisioning_api/lib/groups.php | 35 +- apps/provisioning_api/tests/groupstest.php | 376 ++++++++++++++------- 3 files changed, 277 insertions(+), 137 deletions(-) diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php index dcf18e0e53b..db7dc0d5b42 100644 --- a/apps/provisioning_api/appinfo/routes.php +++ b/apps/provisioning_api/appinfo/routes.php @@ -51,7 +51,8 @@ API::register('get', '/cloud/users/{userid}/subadmins', [$users, 'getUserSubAdmi // Groups $groups = new \OCA\Provisioning_API\Groups( \OC::$server->getGroupManager(), - \OC::$server->getUserSession() + \OC::$server->getUserSession(), + \OC::$server->getRequest() ); API::register('get', '/cloud/groups', [$groups, 'getGroups'], 'provisioning_api', API::SUBADMIN_AUTH); API::register('post', '/cloud/groups', [$groups, 'addGroup'], 'provisioning_api', API::SUBADMIN_AUTH); diff --git a/apps/provisioning_api/lib/groups.php b/apps/provisioning_api/lib/groups.php index c28db35972f..7c35caca5fd 100644 --- a/apps/provisioning_api/lib/groups.php +++ b/apps/provisioning_api/lib/groups.php @@ -37,14 +37,20 @@ class Groups{ /** @var \OCP\IUserSession */ private $userSession; + /** @var \OCP\IRequest */ + private $request; + /** * @param \OCP\IGroupManager $groupManager * @param \OCP\IUserSession $userSession + * @param \OCP\IRequest $request */ public function __construct(\OCP\IGroupManager $groupManager, - \OCP\IUserSession $userSession) { + \OCP\IUserSession $userSession, + \OCP\IRequest $request) { $this->groupManager = $groupManager; $this->userSession = $userSession; + $this->request = $request; } /** @@ -54,9 +60,16 @@ class Groups{ * @return OC_OCS_Result */ public function getGroups($parameters) { - $search = !empty($_GET['search']) ? $_GET['search'] : ''; - $limit = !empty($_GET['limit']) ? $_GET['limit'] : null; - $offset = !empty($_GET['offset']) ? $_GET['offset'] : null; + $search = $this->request->getParam('search', ''); + $limit = $this->request->getParam('limit'); + $offset = $this->request->getParam('offset'); + + if ($limit !== null) { + $limit = (int)$limit; + } + if ($offset !== null) { + $offset = (int)$offset; + } $groups = $this->groupManager->search($search, $limit, $offset); $groups = array_map(function($group) { @@ -80,21 +93,23 @@ class Groups{ return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } + $groupId = $parameters['groupid']; + // Check the group exists - if(!$this->groupManager->groupExists($parameters['groupid'])) { + if(!$this->groupManager->groupExists($groupId)) { return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested group could not be found'); } $isSubadminOfGroup = false; - $targetGroupObject =$this->groupManager->get($parameters['groupid']); - if($targetGroupObject !== null) { - $isSubadminOfGroup =$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $targetGroupObject); + $group = $this->groupManager->get($groupId); + if ($group !== null) { + $isSubadminOfGroup =$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $group); } // Check subadmin has access to this group if($this->groupManager->isAdmin($user->getUID()) || $isSubadminOfGroup) { - $users = $this->groupManager->get($parameters['groupid'])->getUsers(); + $users = $this->groupManager->get($groupId)->getUsers(); $users = array_map(function($user) { /** @var IUser $user */ return $user->getUID(); @@ -114,7 +129,7 @@ class Groups{ */ public function addGroup($parameters) { // Validate name - $groupId = isset($_POST['groupid']) ? $_POST['groupid'] : ''; + $groupId = $this->request->getParam('groupid', ''); if( preg_match( '/[^a-zA-Z0-9 _\.@\-]/', $groupId ) || empty($groupId)){ \OCP\Util::writeLog('provisioning_api', 'Attempt made to create group using invalid characters.', \OCP\Util::ERROR); return new OC_OCS_Result(null, 101, 'Invalid group name'); diff --git a/apps/provisioning_api/tests/groupstest.php b/apps/provisioning_api/tests/groupstest.php index f67ed1c36ae..7d4beb6a368 100644 --- a/apps/provisioning_api/tests/groupstest.php +++ b/apps/provisioning_api/tests/groupstest.php @@ -25,79 +25,131 @@ namespace OCA\Provisioning_API\Tests; -use OCP\IUserManager; use OCP\IGroupManager; use OCP\IUserSession; +use OCP\IRequest; -class GroupsTest extends TestCase { - /** @var IUserManager */ - protected $userManager; +class GroupsTest extends \Test\TestCase { /** @var IGroupManager */ protected $groupManager; /** @var IUserSession */ protected $userSession; + /** @var IRequest */ + protected $request; + /** @var \OC\SubAdmin */ + protected $subAdminManager; /** @var \OCA\Provisioning_API\Groups */ protected $api; protected function setup() { - parent::setup(); + $this->subAdminManager = $this->getMockBuilder('OC\SubAdmin')->disableOriginalConstructor()->getMock(); - $this->userManager = \OC::$server->getUserManager(); - $this->groupManager = \OC::$server->getGroupManager(); - $this->userSession = \OC::$server->getUserSession(); + $this->groupManager = $this->getMockBuilder('OC\Group\Manager')->disableOriginalConstructor()->getMock(); + $this->groupManager + ->method('getSubAdmin') + ->willReturn($this->subAdminManager); + + $this->userSession = $this->getMock('OCP\IUserSession'); + $this->request = $this->getMock('OCP\IRequest'); $this->api = new \OCA\Provisioning_API\Groups( $this->groupManager, - $this->userSession + $this->userSession, + $this->request ); } - public function testGetGroups() { - $groups = []; - $id = $this->getUniqueID(); + private function createGroup($gid) { + $group = $this->getMock('OCP\IGroup'); + $group + ->method('getGID') + ->willReturn($gid); + return $group; + } - for ($i=0; $i < 10; $i++) { - $groups[] = $this->groupManager->createGroup($id . '_' . $i); - } + private function createUser($uid) { + $user = $this->getMock('OCP\IUser'); + $user + ->method('getUID') + ->willReturn($uid); + return $user; + } - $_GET = []; - $result = $this->api->getGroups([]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertCount(count($this->groupManager->search('')), $result->getData()['groups']); - $this->assertContains('admin', $result->getData()['groups']); - foreach ($groups as $group) { - $this->assertContains($group->getGID(), $result->getData()['groups']); - } - - $_GET = [ - 'search' => $id, - 'limit' => 5, - 'offset' => 2 + private function asUser() { + $user = $this->createUser('user'); + $this->userSession + ->method('getUser') + ->willReturn($user); + } + + private function asAdmin() { + $user = $this->createUser('admin'); + $this->userSession + ->method('getUser') + ->willReturn($user); + + $this->groupManager + ->method('isAdmin') + ->with('admin') + ->willReturn(true); + } + + private function asSubAdminOfGroup($group) { + $user = $this->createUser('subAdmin'); + $this->userSession + ->method('getUser') + ->willReturn($user); + + $this->subAdminManager + ->method('isSubAdminOfGroup') + ->will($this->returnCallback(function($_user, $_group) use ($user, $group) { + if ($_user === $user && $_group === $group) { + return true; + } + return false; + })); + } + + public function dataGetGroups() { + return [ + [null, null, null], + ['foo', null, null], + [null, 1, null], + [null, null, 2], + ['foo', 1, 2], ]; + } + + /** + * @dataProvider dataGetGroups + */ + public function testGetGroups($search, $limit, $offset) { + $this->request + ->expects($this->exactly(3)) + ->method('getParam') + ->will($this->returnValueMap([ + ['search', '', $search], + ['limit', null, $limit], + ['offset', null, $offset], + ])); + + $groups = [$this->createGroup('group1'), $this->createGroup('group2')]; + + $search = $search === null ? '' : $search; + + $this->groupManager + ->expects($this->once()) + ->method('search') + ->with($search, $limit, $offset) + ->willReturn($groups); + $result = $this->api->getGroups([]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertTrue($result->succeeded()); - $this->assertCount(5, $result->getData()['groups']); - foreach (array_splice($groups, 2, 5) as $group) { - $this->assertContains($group->getGID(), $result->getData()['groups']); - } - - foreach ($groups as $group) { - $group->delete(); - } + $this->assertEquals(['group1', 'group2'], $result->getData()['groups']); } public function testGetGroupAsUser() { - - $users = $this->generateUsers(2); - $this->userSession->setUser($users[0]); - - $group = $this->groupManager->createGroup($this->getUniqueID()); - $group->addUser($users[1]); - - $result = $this->api->getGroup(array( - 'groupid' => $group->getGID(), - )); + $result = $this->api->getGroup([]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertFalse($result->succeeded()); @@ -106,80 +158,91 @@ class GroupsTest extends TestCase { } public function testGetGroupAsSubadmin() { - - $users = $this->generateUsers(2); - $this->userSession->setUser($users[0]); - - $group = $this->groupManager->createGroup($this->getUniqueID()); - $group->addUser($users[0]); - $group->addUser($users[1]); - - $this->groupManager->getSubAdmin()->createSubAdmin($users[0], $group); + $group = $this->createGroup('group'); + $this->asSubAdminOfGroup($group); + + $this->groupManager + ->method('get') + ->with('group') + ->willReturn($group); + $this->groupManager + ->method('groupExists') + ->with('group') + ->willReturn(true); + $group + ->method('getUsers') + ->willReturn([ + $this->createUser('user1'), + $this->createUser('user2') + ]); $result = $this->api->getGroup([ - 'groupid' => $group->getGID(), + 'groupid' => 'group', ]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertTrue($result->succeeded()); $this->assertEquals(1, sizeof($result->getData()), 'Asserting the result data array only has the "users" key'); $this->assertArrayHasKey('users', $result->getData()); - $resultData = $result->getData(); - $resultData = $resultData['users']; - - $users = array_map(function($user) { - return $user->getUID(); - }, $users); - - sort($users); - sort($resultData); - $this->assertEquals($users, $resultData); - + $this->assertEquals(['user1', 'user2'], $result->getData()['users']); } public function testGetGroupAsIrrelevantSubadmin() { - - $users = $this->generateUsers(2); - $this->userSession->setUser($users[0]); - - $group1 = $this->groupManager->createGroup($this->getUniqueID()); - $group2 = $this->groupManager->createGroup($this->getUniqueID()); - $group1->addUser($users[1]); - $group2->addUser($users[0]); - - $this->groupManager->getSubAdmin()->createSubAdmin($users[0], $group2); + $group = $this->createGroup('group'); + $otherGroup = $this->createGroup('otherGroup'); + $this->asSubAdminOfGroup($otherGroup); + + $this->groupManager + ->method('get') + ->with('group') + ->willReturn($group); + $this->groupManager + ->method('groupExists') + ->with('group') + ->willReturn(true); $result = $this->api->getGroup([ - 'groupid' => $group1->getGID(), + 'groupid' => 'group', ]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertFalse($result->succeeded()); $this->assertEquals(\OCP\API::RESPOND_UNAUTHORISED, $result->getStatusCode()); - } public function testGetGroupAsAdmin() { - - $users = $this->generateUsers(2); - $this->userSession->setUser($users[0]); - - $group = $this->groupManager->createGroup($this->getUniqueID()); - - $group->addUser($users[1]); - $this->groupManager->get('admin')->addUser($users[0]); + $group = $this->createGroup('group'); + $this->asAdmin(); + + $this->groupManager + ->method('get') + ->with('group') + ->willReturn($group); + $this->groupManager + ->method('groupExists') + ->with('group') + ->willReturn(true); + $group + ->method('getUsers') + ->willReturn([ + $this->createUser('user1'), + $this->createUser('user2') + ]); $result = $this->api->getGroup([ - 'groupid' => $group->getGID(), + 'groupid' => 'group', ]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertTrue($result->succeeded()); - $this->assertEquals(['users' => [$users[1]->getUID()]], $result->getData()); - + $this->assertEquals(1, sizeof($result->getData()), 'Asserting the result data array only has the "users" key'); + $this->assertArrayHasKey('users', $result->getData()); + $this->assertEquals(['user1', 'user2'], $result->getData()['users']); } public function testGetGroupNonExisting() { + $this->asUser(); + $result = $this->api->getGroup([ 'groupid' => $this->getUniqueId() ]); @@ -190,35 +253,72 @@ class GroupsTest extends TestCase { $this->assertEquals('The requested group could not be found', $result->getMeta()['message']); } + public function testGetSubAdminsOfGroupsNotExists() { + $result = $this->api->getSubAdminsOfGroup([ + 'groupid' => 'NonExistingGroup', + ]); + + $this->assertInstanceOf('OC_OCS_Result', $result); + $this->assertFalse($result->succeeded()); + $this->assertEquals(101, $result->getStatusCode()); + $this->assertEquals('Group does not exist', $result->getMeta()['message']); + } + public function testGetSubAdminsOfGroup() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->groupManager->createGroup($this->getUniqueID()); - $this->groupManager->getSubAdmin()->createSubAdmin($user2, $group1); + $group = $this->createGroup('GroupWithSubAdmins'); + $this->groupManager + ->method('get') + ->with('GroupWithSubAdmins') + ->willReturn($group); + + $this->subAdminManager + ->expects($this->once()) + ->method('getGroupsSubAdmins') + ->with($group) + ->willReturn([ + $this->createUser('SubAdmin1'), + $this->createUser('SubAdmin2'), + ]); + $result = $this->api->getSubAdminsOfGroup([ - 'groupid' => $group1->getGID(), + 'groupid' => 'GroupWithSubAdmins', ]); + $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals($user2->getUID(), reset($data)); - $group1->delete(); + $this->assertEquals(['SubAdmin1', 'SubAdmin2'], $result->getData()); + } + + public function testGetSubAdminsOfGroupEmptyList() { + $group = $this->createGroup('GroupWithOutSubAdmins'); + $this->groupManager + ->method('get') + ->with('GroupWithOutSubAdmins') + ->willReturn($group); + + $this->subAdminManager + ->expects($this->once()) + ->method('getGroupsSubAdmins') + ->with($group) + ->willReturn([ + ]); - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); $result = $this->api->getSubAdminsOfGroup([ - 'groupid' => $this->getUniqueID(), + 'groupid' => 'GroupWithOutSubAdmins', ]); + $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); + $this->assertEquals(102, $result->getStatusCode()); + $this->assertEquals('Unknown error occured', $result->getMeta()['message']); } public function testAddGroupEmptyGroup() { - $_POST = []; + $this->request + ->method('getParam') + ->with('groupid') + ->willReturn(''); + $result = $this->api->addGroup([]); $this->assertInstanceOf('OC_OCS_Result', $result); @@ -228,40 +328,47 @@ class GroupsTest extends TestCase { } public function testAddGroupExistingGroup() { - $group = $this->groupManager->createGroup($this->getUniqueID()); + $this->request + ->method('getParam') + ->with('groupid') + ->willReturn('ExistingGroup'); + + $this->groupManager + ->method('groupExists') + ->with('ExistingGroup') + ->willReturn(true); - $_POST = [ - 'groupid' => $group->getGID() - ]; $result = $this->api->addGroup([]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertFalse($result->succeeded()); $this->assertEquals(102, $result->getStatusCode()); - - $group->delete(); } public function testAddGroup() { - $group = $this->getUniqueId(); + $this->request + ->method('getParam') + ->with('groupid') + ->willReturn('NewGroup'); - $_POST = [ - 'groupid' => $group - ]; + $this->groupManager + ->method('groupExists') + ->with('NewGroup') + ->willReturn(false); + + $this->groupManager + ->expects($this->once()) + ->method('createGroup') + ->with('NewGroup'); $result = $this->api->addGroup([]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertTrue($result->succeeded()); - $this->assertTrue($this->groupManager->groupExists($group)); - - $this->groupManager->get($group)->delete(); } public function testDeleteGroupNonExisting() { - $group = $this->getUniqueId(); - $result = $this->api->deleteGroup([ - 'groupid' => $group + 'groupid' => 'NonExistingGroup' ]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertFalse($result->succeeded()); @@ -269,6 +376,11 @@ class GroupsTest extends TestCase { } public function testDeleteAdminGroup() { + $this->groupManager + ->method('groupExists') + ->with('admin') + ->willReturn('true'); + $result = $this->api->deleteGroup([ 'groupid' => 'admin' ]); @@ -278,13 +390,25 @@ class GroupsTest extends TestCase { } public function testDeleteGroup() { - $group = $this->groupManager->createGroup($this->getUniqueId()); + $this->groupManager + ->method('groupExists') + ->with('ExistingGroup') + ->willReturn('true'); + + $group = $this->createGroup('ExistingGroup'); + $this->groupManager + ->method('get') + ->with('ExistingGroup') + ->willReturn($group); + $group + ->expects($this->once()) + ->method('delete') + ->willReturn(true); $result = $this->api->deleteGroup([ - 'groupid' => $group->getGID() + 'groupid' => 'ExistingGroup', ]); $this->assertInstanceOf('OC_OCS_Result', $result); $this->assertTrue($result->succeeded()); - $this->assertFalse($this->groupManager->groupExists($group->getGID())); } } -- GitLab From 5b72d9026f092cf82ee405a48117bfc4f075fbc2 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Tue, 10 Nov 2015 17:30:19 +0100 Subject: [PATCH 038/344] standardize sizes for headings --- apps/files/templates/appnavigation.php | 4 +--- core/css/apps.css | 9 ++++++--- core/css/styles.css | 2 -- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php index 512300e3a58..d05a02ee7db 100644 --- a/apps/files/templates/appnavigation.php +++ b/apps/files/templates/appnavigation.php @@ -16,9 +16,7 @@
-

- -

+ t('Use this address to access your Files via WebDAV', array(link_to_docs('user-webdav'))));?>
diff --git a/core/css/apps.css b/core/css/apps.css index ac2be40ac5b..e9abbe0aee1 100644 --- a/core/css/apps.css +++ b/core/css/apps.css @@ -563,16 +563,19 @@ button.loading { #app-content > .section:first-child { border-top: none; } -.section h2 { + +/* heading styles */ +h2 { font-size: 20px; - margin-bottom: 12px; font-weight: 300; + margin-bottom: 12px; } -.section h3 { +h3 { font-size: 15px; font-weight: 300; margin: 12px 0; } + /* slight position correction of checkboxes and radio buttons */ .section input[type="checkbox"], .section input[type="radio"] { diff --git a/core/css/styles.css b/core/css/styles.css index 066087cc433..8adafb22185 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -437,7 +437,6 @@ input[type="submit"].enabled { #emptycontent h2, .emptycontent h2 { font-weight: 600; - font-size: 22px; margin-bottom: 10px; } #emptycontent [class^="icon-"], @@ -483,7 +482,6 @@ input[type="submit"].enabled { } #body-login .update h2 { - font-size: 20px; line-height: 130%; margin-bottom: 30px; } -- GitLab From 67710e62fa8cd5f875ee722766aeafdc72f3861e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 16 Nov 2015 14:56:03 +0100 Subject: [PATCH 039/344] Fix parsing of sftp hosts when using ipv6 --- apps/files_external/lib/sftp.php | 38 +++++++++++++-------- apps/files_external/tests/backends/sftp.php | 38 +++++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/apps/files_external/lib/sftp.php b/apps/files_external/lib/sftp.php index 5dcc7686ca3..f8651727fd2 100644 --- a/apps/files_external/lib/sftp.php +++ b/apps/files_external/lib/sftp.php @@ -51,6 +51,27 @@ class SFTP extends \OC\Files\Storage\Common { */ protected $client; + /** + * @param string $host protocol://server:port + * @return array [$server, $port] + */ + private function splitHost($host) { + $input = $host; + if (strpos($host, '://') === false) { + // add a protocol to fix parse_url behavior with ipv6 + $host = 'http://' . $host; + } + + $parsed = parse_url($host); + if(is_array($parsed) && isset($parsed['port'])) { + return [$parsed['host'], $parsed['port']]; + } else if (is_array($parsed)) { + return [$parsed['host'], 22]; + } else { + return [$input, 22]; + } + } + /** * {@inheritdoc} */ @@ -58,21 +79,10 @@ class SFTP extends \OC\Files\Storage\Common { // Register sftp:// Stream::register(); - $this->host = $params['host']; + $parsedHost = $this->splitHost($params['host']); - //deals with sftp://server example - $proto = strpos($this->host, '://'); - if ($proto != false) { - $this->host = substr($this->host, $proto+3); - } - - //deals with server:port - $hasPort = strpos($this->host,':'); - if($hasPort != false) { - $pieces = explode(":", $this->host); - $this->host = $pieces[0]; - $this->port = $pieces[1]; - } + $this->host = $parsedHost[0]; + $this->port = $parsedHost[1]; $this->user = $params['user']; diff --git a/apps/files_external/tests/backends/sftp.php b/apps/files_external/tests/backends/sftp.php index da2c0ac6ba2..aaed2b3460a 100644 --- a/apps/files_external/tests/backends/sftp.php +++ b/apps/files_external/tests/backends/sftp.php @@ -26,6 +26,11 @@ namespace Test\Files\Storage; class SFTP extends Storage { + /** + * @var \OC\Files\Storage\SFTP instance + */ + protected $instance; + private $config; protected function setUp() { @@ -103,6 +108,39 @@ class SFTP extends Storage { ], 'sftp::someuser@somehost:8822//remotedir/subdir/', ], + [ + // ipv6 with port + [ + 'run' => true, + 'host' => 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329', + 'user' => 'someuser', + 'password' => 'somepassword', + 'root' => 'remotedir/subdir/', + ], + 'sftp::someuser@FE80:0000:0000:0000:0202:B3FF:FE1E:8329//remotedir/subdir/', + ], + [ + // ipv6 without port + [ + 'run' => true, + 'host' => 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329:8822', + 'user' => 'someuser', + 'password' => 'somepassword', + 'root' => 'remotedir/subdir/', + ], + 'sftp::someuser@FE80:0000:0000:0000:0202:B3FF:FE1E:8329:8822//remotedir/subdir/', + ], + [ + // collapsed ipv6 with port + [ + 'run' => true, + 'host' => 'FE80::0202:B3FF:FE1E:8329:8822', + 'user' => 'someuser', + 'password' => 'somepassword', + 'root' => 'remotedir/subdir/', + ], + 'sftp::someuser@FE80::0202:B3FF:FE1E:8329:8822//remotedir/subdir/', + ], ]; } } -- GitLab From 23e7a62717fe6ee84c54ce1d3c601b477119696e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 15:28:34 +0100 Subject: [PATCH 040/344] Fix Oracle --- apps/dav/lib/caldav/caldavbackend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php index cd41fd1f044..6dd60c43336 100644 --- a/apps/dav/lib/caldav/caldavbackend.php +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -902,7 +902,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription ]) ->execute(); - return $this->db->lastInsertId(); + return $this->db->lastInsertId('*PREFIX*calendarsubscriptions'); } /** -- GitLab From d62f410f92f32008edd3d127b1005b4754a54319 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 2 Nov 2015 15:05:16 +0100 Subject: [PATCH 041/344] Add "owner-id" and "owner-display-name" Webdav properties --- apps/dav/lib/connector/sabre/filesplugin.php | 14 ++++++ apps/dav/lib/connector/sabre/node.php | 4 ++ .../unit/connector/sabre/filesplugin.php | 50 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/apps/dav/lib/connector/sabre/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php index 61b5360cac1..00d5d2cd725 100644 --- a/apps/dav/lib/connector/sabre/filesplugin.php +++ b/apps/dav/lib/connector/sabre/filesplugin.php @@ -42,6 +42,8 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size'; const GETETAG_PROPERTYNAME = '{DAV:}getetag'; const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified'; + const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id'; + const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name'; /** * Reference to main server object @@ -99,6 +101,8 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME; $server->protectedProperties[] = self::SIZE_PROPERTYNAME; $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME; + $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME; + $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME; // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH $allowedProperties = ['{DAV:}getetag']; @@ -201,6 +205,16 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { return $node->getSize(); }); } + + $propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) { + $owner = $node->getOwner(); + return $owner->getUID(); + }); + $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) { + $owner = $node->getOwner(); + $displayName = $owner->getDisplayName(); + return $displayName; + }); } /** diff --git a/apps/dav/lib/connector/sabre/node.php b/apps/dav/lib/connector/sabre/node.php index 814aaceb077..ae7dd51fc94 100644 --- a/apps/dav/lib/connector/sabre/node.php +++ b/apps/dav/lib/connector/sabre/node.php @@ -238,6 +238,10 @@ abstract class Node implements \Sabre\DAV\INode { return $p; } + public function getOwner() { + return $this->info->getOwner(); + } + protected function verifyPath() { try { $fileName = basename($this->info->getPath()); diff --git a/apps/dav/tests/unit/connector/sabre/filesplugin.php b/apps/dav/tests/unit/connector/sabre/filesplugin.php index f3c862941c0..55c8dd49e17 100644 --- a/apps/dav/tests/unit/connector/sabre/filesplugin.php +++ b/apps/dav/tests/unit/connector/sabre/filesplugin.php @@ -15,6 +15,8 @@ class FilesPlugin extends \Test\TestCase { const PERMISSIONS_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::PERMISSIONS_PROPERTYNAME; const LASTMODIFIED_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::LASTMODIFIED_PROPERTYNAME; const DOWNLOADURL_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::DOWNLOADURL_PROPERTYNAME; + const OWNER_ID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::OWNER_ID_PROPERTYNAME; + const OWNER_DISPLAY_NAME_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME; /** * @var \Sabre\DAV\Server @@ -91,13 +93,29 @@ class FilesPlugin extends \Test\TestCase { self::SIZE_PROPERTYNAME, self::PERMISSIONS_PROPERTYNAME, self::DOWNLOADURL_PROPERTYNAME, + self::OWNER_ID_PROPERTYNAME, + self::OWNER_DISPLAY_NAME_PROPERTYNAME ), 0 ); + $user = $this->getMockBuilder('\OC\User\User') + ->disableOriginalConstructor()->getMock(); + $user + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('foo')); + $user + ->expects($this->once()) + ->method('getDisplayName') + ->will($this->returnValue('M. Foo')); + $node->expects($this->once()) ->method('getDirectDownload') ->will($this->returnValue(array('url' => 'http://example.com/'))); + $node->expects($this->exactly(2)) + ->method('getOwner') + ->will($this->returnValue($user)); $node->expects($this->never()) ->method('getSize'); @@ -111,6 +129,8 @@ class FilesPlugin extends \Test\TestCase { $this->assertEquals(null, $propFind->get(self::SIZE_PROPERTYNAME)); $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME)); $this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME)); + $this->assertEquals('foo', $propFind->get(self::OWNER_ID_PROPERTYNAME)); + $this->assertEquals('M. Foo', $propFind->get(self::OWNER_DISPLAY_NAME_PROPERTYNAME)); $this->assertEquals(array(self::SIZE_PROPERTYNAME), $propFind->get404Properties()); } @@ -207,6 +227,36 @@ class FilesPlugin extends \Test\TestCase { $this->assertEquals(200, $result[self::GETETAG_PROPERTYNAME]); } + public function testUpdatePropsForbidden() { + $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File'); + + $propPatch = new \Sabre\DAV\PropPatch(array( + self::OWNER_ID_PROPERTYNAME => 'user2', + self::OWNER_DISPLAY_NAME_PROPERTYNAME => 'User Two', + self::FILEID_PROPERTYNAME => 12345, + self::PERMISSIONS_PROPERTYNAME => 'C', + self::SIZE_PROPERTYNAME => 123, + self::DOWNLOADURL_PROPERTYNAME => 'http://example.com/', + )); + + $this->plugin->handleUpdateProperties( + '/dummypath', + $propPatch + ); + + $propPatch->commit(); + + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(403, $result[self::OWNER_ID_PROPERTYNAME]); + $this->assertEquals(403, $result[self::OWNER_DISPLAY_NAME_PROPERTYNAME]); + $this->assertEquals(403, $result[self::FILEID_PROPERTYNAME]); + $this->assertEquals(403, $result[self::PERMISSIONS_PROPERTYNAME]); + $this->assertEquals(403, $result[self::SIZE_PROPERTYNAME]); + $this->assertEquals(403, $result[self::DOWNLOADURL_PROPERTYNAME]); + } + /** * Testcase from https://github.com/owncloud/core/issues/5251 * -- GitLab From 867fd94dc663652da1465de8537f01b8c7b4db07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 15:49:46 +0100 Subject: [PATCH 042/344] Add scheduling backend --- apps/dav/lib/caldav/caldavbackend.php | 58 +++++++++++++++++-- .../tests/unit/caldav/caldavbackendtest.php | 14 +++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php index 6dd60c43336..4dcd1bed3de 100644 --- a/apps/dav/lib/caldav/caldavbackend.php +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -982,7 +982,26 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array */ function getSchedulingObject($principalUri, $objectUri) { - // TODO: Implement getSchedulingObject() method. + $query = $this->db->getQueryBuilder(); + $stmt = $query->select(['uri', 'calendardata', 'lastmodified', 'etag', 'size']) + ->from('schedulingobjects') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))) + ->execute(); + + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + + if(!$row) { + return null; + } + + return [ + 'uri' => $row['uri'], + 'calendardata' => $row['calendardata'], + 'lastmodified' => $row['lastmodified'], + 'etag' => '"' . $row['etag'] . '"', + 'size' => (int)$row['size'], + ]; } /** @@ -997,7 +1016,24 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array */ function getSchedulingObjects($principalUri) { - // TODO: Implement getSchedulingObjects() method. + $query = $this->db->getQueryBuilder(); + $stmt = $query->select(['uri', 'calendardata', 'lastmodified', 'etag', 'size']) + ->from('schedulingobjects') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))) + ->execute(); + + $result = []; + foreach($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) { + $result[] = [ + 'calendardata' => $row['calendardata'], + 'uri' => $row['uri'], + 'lastmodified' => $row['lastmodified'], + 'etag' => '"' . $row['etag'] . '"', + 'size' => (int)$row['size'], + ]; + } + + return $result; } /** @@ -1008,7 +1044,11 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return void */ function deleteSchedulingObject($principalUri, $objectUri) { - // TODO: Implement deleteSchedulingObject() method. + $query = $this->db->getQueryBuilder(); + $query->delete('schedulingobjects') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))) + ->execute(); } /** @@ -1020,7 +1060,17 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return void */ function createSchedulingObject($principalUri, $objectUri, $objectData) { - // TODO: Implement createSchedulingObject() method. + $query = $this->db->getQueryBuilder(); + $query->insert('schedulingobjects') + ->values([ + 'principaluri' => $query->createNamedParameter($principalUri), + 'calendardata' => $query->createNamedParameter($objectData), + 'uri' => $query->createNamedParameter($objectUri), + 'lastmodified' => $query->createNamedParameter(time()), + 'etag' => $query->createNamedParameter(md5($objectData)), + 'size' => $query->createNamedParameter(strlen($objectData)) + ]) + ->execute(); } /** diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php index beb88a398b9..5e3d4288aa7 100644 --- a/apps/dav/tests/unit/caldav/caldavbackendtest.php +++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php @@ -322,4 +322,18 @@ EOD; $this->assertEquals(0, count($subscriptions)); } + public function testScheduling() { + $this->backend->createSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule', ''); + + $sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER); + $this->assertEquals(1, count($sos)); + + $so = $this->backend->getSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule'); + $this->assertNotNull($so); + + $this->backend->deleteSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule'); + + $sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER); + $this->assertEquals(0, count($sos)); + } } -- GitLab From 5fc414abfdb959494f1be51bfbd3f148c4aa9205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 16:09:04 +0100 Subject: [PATCH 043/344] Add internal locking plugin - fixes #20502 --- apps/dav/lib/connector/sabre/lockplugin.php | 16 ++-------------- apps/dav/lib/connector/sabre/serverfactory.php | 2 +- apps/dav/lib/server.php | 7 +++++++ 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/apps/dav/lib/connector/sabre/lockplugin.php b/apps/dav/lib/connector/sabre/lockplugin.php index 5840e59854c..8032d2b3fbf 100644 --- a/apps/dav/lib/connector/sabre/lockplugin.php +++ b/apps/dav/lib/connector/sabre/lockplugin.php @@ -38,18 +38,6 @@ class LockPlugin extends ServerPlugin { */ private $server; - /** - * @var \Sabre\DAV\Tree - */ - private $tree; - - /** - * @param \Sabre\DAV\Tree $tree tree - */ - public function __construct(Tree $tree) { - $this->tree = $tree; - } - /** * {@inheritdoc} */ @@ -66,7 +54,7 @@ class LockPlugin extends ServerPlugin { return; } try { - $node = $this->tree->getNodeForPath($request->getPath()); + $node = $this->server->tree->getNodeForPath($request->getPath()); } catch (NotFound $e) { return; } @@ -84,7 +72,7 @@ class LockPlugin extends ServerPlugin { return; } try { - $node = $this->tree->getNodeForPath($request->getPath()); + $node = $this->server->tree->getNodeForPath($request->getPath()); } catch (NotFound $e) { return; } diff --git a/apps/dav/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php index a33acc9f00b..0f0377e96bd 100644 --- a/apps/dav/lib/connector/sabre/serverfactory.php +++ b/apps/dav/lib/connector/sabre/serverfactory.php @@ -107,7 +107,7 @@ class ServerFactory { // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to / $server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin()); $server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger)); - $server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin($objectTree)); + $server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin()); $server->addPlugin(new \OCA\DAV\Connector\Sabre\ListenerPlugin($this->dispatcher)); // Finder on OS X requires Class 2 WebDAV support (locking), since we do // not provide locking we emulate it using a fake locking plugin. diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index 395544761ab..535677c2c35 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -17,6 +17,9 @@ class Server { public function __construct(IRequest $request, $baseUri) { $this->request = $request; $this->baseUri = $baseUri; + $logger = \OC::$server->getLogger(); + $dispatcher = \OC::$server->getEventDispatcher(); + $root = new RootCollection(); $this->server = new \OCA\DAV\Connector\Sabre\Server($root); @@ -32,6 +35,10 @@ class Server { $this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig())); $this->server->addPlugin(new Plugin($authBackend, 'ownCloud')); + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin()); + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $logger)); + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin()); + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ListenerPlugin($dispatcher)); $this->server->addPlugin(new \Sabre\DAVACL\Plugin()); -- GitLab From 1666af89c2db24e05dfc8480e087fc73bb32e831 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 16 Nov 2015 16:14:52 +0100 Subject: [PATCH 044/344] Add "is primary action" to actions --- lib/private/notification/action.php | 24 ++++++++++++++ lib/private/notification/iaction.php | 13 ++++++++ lib/private/notification/notification.php | 24 ++++++++++++++ tests/lib/notification/notificationtest.php | 36 +++++++++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/lib/private/notification/action.php b/lib/private/notification/action.php index 6de8a1a4bbc..e1171531716 100644 --- a/lib/private/notification/action.php +++ b/lib/private/notification/action.php @@ -39,6 +39,9 @@ class Action implements IAction { /** @var string */ protected $icon; + /** @var bool */ + protected $primary; + /** * Constructor */ @@ -94,6 +97,27 @@ class Action implements IAction { return $this->labelParsed; } + /** + * @param $primary bool + * @throws \InvalidArgumentException if $primary is invalid + * @since 9.0.0 + */ + public function setPrimary($primary) { + if (!is_bool($primary)) { + throw new \InvalidArgumentException('The given primary option is invalid'); + } + + $this->primary = $primary; + } + + /** + * @return bool + * @since 9.0.0 + */ + public function isPrimary() { + return $this->primary; + } + /** * @param string $link * @param string $requestType diff --git a/lib/private/notification/iaction.php b/lib/private/notification/iaction.php index da6728f5c52..9fd964e3dcf 100644 --- a/lib/private/notification/iaction.php +++ b/lib/private/notification/iaction.php @@ -60,6 +60,19 @@ interface IAction { */ public function getParsedLabel(); + /** + * @param $primary bool + * @throws \InvalidArgumentException if $primary is invalid + * @since 9.0.0 + */ + public function setPrimary($primary); + + /** + * @return bool + * @since 9.0.0 + */ + public function isPrimary(); + /** * @param string $link * @param string $requestType diff --git a/lib/private/notification/notification.php b/lib/private/notification/notification.php index 40fe39a956e..15ca0fee5d2 100644 --- a/lib/private/notification/notification.php +++ b/lib/private/notification/notification.php @@ -68,6 +68,12 @@ class Notification implements INotification { /** @var array */ protected $actionsParsed; + /** @var bool */ + protected $hasPrimaryAction; + + /** @var bool */ + protected $hasPrimaryParsedAction; + /** * Constructor */ @@ -369,6 +375,15 @@ class Notification implements INotification { if (!$action->isValid()) { throw new \InvalidArgumentException('The given action is invalid'); } + + if ($action->isPrimary()) { + if ($this->hasPrimaryAction) { + throw new \InvalidArgumentException('The notification already has a primary action'); + } + + $this->hasPrimaryAction = true; + } + $this->actions[] = $action; return $this; } @@ -391,6 +406,15 @@ class Notification implements INotification { if (!$action->isValidParsed()) { throw new \InvalidArgumentException('The given parsed action is invalid'); } + + if ($action->isPrimary()) { + if ($this->hasPrimaryParsedAction) { + throw new \InvalidArgumentException('The notification already has a primary action'); + } + + $this->hasPrimaryParsedAction = true; + } + $this->actionsParsed[] = $action; return $this; } diff --git a/tests/lib/notification/notificationtest.php b/tests/lib/notification/notificationtest.php index a790a53eaa7..98dc0e5bacd 100644 --- a/tests/lib/notification/notificationtest.php +++ b/tests/lib/notification/notificationtest.php @@ -438,6 +438,24 @@ class NotificationTest extends TestCase { $this->notification->addAction($action); } + public function testAddActionSecondPrimary() { + /** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ + $action = $this->getMockBuilder('OC\Notification\IAction') + ->disableOriginalConstructor() + ->getMock(); + $action->expects($this->exactly(2)) + ->method('isValid') + ->willReturn(true); + $action->expects($this->exactly(2)) + ->method('isPrimary') + ->willReturn(true); + + $this->notification->addAction($action); + + $this->setExpectedException('\InvalidArgumentException'); + $this->notification->addAction($action); + } + public function testAddParsedAction() { /** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ $action = $this->getMockBuilder('OC\Notification\IAction') @@ -472,6 +490,24 @@ class NotificationTest extends TestCase { $this->notification->addParsedAction($action); } + public function testAddActionSecondParsedPrimary() { + /** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ + $action = $this->getMockBuilder('OC\Notification\IAction') + ->disableOriginalConstructor() + ->getMock(); + $action->expects($this->exactly(2)) + ->method('isValidParsed') + ->willReturn(true); + $action->expects($this->exactly(2)) + ->method('isPrimary') + ->willReturn(true); + + $this->notification->addParsedAction($action); + + $this->setExpectedException('\InvalidArgumentException'); + $this->notification->addParsedAction($action); + } + public function dataIsValid() { return [ [false, '', false], -- GitLab From 40d5d5512401673f30ba822ff26b1762c9730da9 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 16 Nov 2015 16:17:23 +0100 Subject: [PATCH 045/344] Remove the icon for now --- lib/private/notification/action.php | 22 ----------- lib/private/notification/iaction.php | 14 ------- lib/private/notification/inotification.php | 14 ------- lib/private/notification/notification.php | 22 ----------- tests/lib/notification/actiontest.php | 41 --------------------- tests/lib/notification/notificationtest.php | 28 -------------- 6 files changed, 141 deletions(-) diff --git a/lib/private/notification/action.php b/lib/private/notification/action.php index e1171531716..958b085b38e 100644 --- a/lib/private/notification/action.php +++ b/lib/private/notification/action.php @@ -153,28 +153,6 @@ class Action implements IAction { return $this->requestType; } - /** - * @param string $icon - * @return $this - * @throws \InvalidArgumentException if the icon is invalid - * @since 8.2.0 - */ - public function setIcon($icon) { - if (!is_string($icon) || $icon === '' || isset($icon[64])) { - throw new \InvalidArgumentException('The given icon is invalid'); - } - $this->icon = $icon; - return $this; - } - - /** - * @return string - * @since 8.2.0 - */ - public function getIcon() { - return $this->icon; - } - /** * @return bool */ diff --git a/lib/private/notification/iaction.php b/lib/private/notification/iaction.php index 9fd964e3dcf..4aed2e92517 100644 --- a/lib/private/notification/iaction.php +++ b/lib/private/notification/iaction.php @@ -94,20 +94,6 @@ interface IAction { */ public function getRequestType(); - /** - * @param string $icon - * @return $this - * @throws \InvalidArgumentException if the icon is invalid - * @since 8.2.0 - */ - public function setIcon($icon); - - /** - * @return string - * @since 8.2.0 - */ - public function getIcon(); - /** * @return bool * @since 8.2.0 diff --git a/lib/private/notification/inotification.php b/lib/private/notification/inotification.php index faf5db1d24c..a8bf5b110ab 100644 --- a/lib/private/notification/inotification.php +++ b/lib/private/notification/inotification.php @@ -179,20 +179,6 @@ interface INotification { */ public function getLink(); - /** - * @param string $icon - * @return $this - * @throws \InvalidArgumentException if the icon are invalid - * @since 8.2.0 - */ - public function setIcon($icon); - - /** - * @return string - * @since 8.2.0 - */ - public function getIcon(); - /** * @return IAction * @since 8.2.0 diff --git a/lib/private/notification/notification.php b/lib/private/notification/notification.php index 15ca0fee5d2..01df659d4a1 100644 --- a/lib/private/notification/notification.php +++ b/lib/private/notification/notification.php @@ -335,28 +335,6 @@ class Notification implements INotification { return $this->link; } - /** - * @param string $icon - * @return $this - * @throws \InvalidArgumentException if the icon are invalid - * @since 8.2.0 - */ - public function setIcon($icon) { - if (!is_string($icon) || $icon === '' || isset($icon[64])) { - throw new \InvalidArgumentException('The given icon is invalid'); - } - $this->icon = $icon; - return $this; - } - - /** - * @return string - * @since 8.2.0 - */ - public function getIcon() { - return $this->icon; - } - /** * @return IAction * @since 8.2.0 diff --git a/tests/lib/notification/actiontest.php b/tests/lib/notification/actiontest.php index e319c250cc7..a6157d6c56e 100644 --- a/tests/lib/notification/actiontest.php +++ b/tests/lib/notification/actiontest.php @@ -171,47 +171,6 @@ class ActionTest extends TestCase { $this->action->setLink($link, $type); } - public function dataSetIcon() { - return [ - ['test1'], - [str_repeat('a', 1)], - [str_repeat('a', 64)], - ]; - } - - /** - * @dataProvider dataSetIcon - * @param string $icon - */ - public function testSetIcon($icon) { - $this->assertSame('', $this->action->getIcon()); - $this->action->setIcon($icon); - $this->assertSame($icon, $this->action->getIcon()); - } - - public function dataSetIconInvalid() { - return [ - [true], - [false], - [0], - [1], - [''], - [str_repeat('a', 65)], - [[]], - [[str_repeat('a', 65)]], - ]; - } - - /** - * @dataProvider dataSetIconInvalid - * @param string $icon - * - * @expectedException \InvalidArgumentException - */ - public function testSetIconInvalid($icon) { - $this->action->setIcon($icon); - } - public function testIsValid() { $this->assertFalse($this->action->isValid()); $this->assertFalse($this->action->isValidParsed()); diff --git a/tests/lib/notification/notificationtest.php b/tests/lib/notification/notificationtest.php index 98dc0e5bacd..8be49ebdc17 100644 --- a/tests/lib/notification/notificationtest.php +++ b/tests/lib/notification/notificationtest.php @@ -371,34 +371,6 @@ class NotificationTest extends TestCase { $this->notification->setLink($link); } - public function dataSetIcon() { - return $this->dataValidString(64); - } - - /** - * @dataProvider dataSetIcon - * @param string $icon - */ - public function testSetIcon($icon) { - $this->assertSame('', $this->notification->getIcon()); - $this->notification->setIcon($icon); - $this->assertSame($icon, $this->notification->getIcon()); - } - - public function dataSetIconInvalid() { - return $this->dataInvalidString(64); - } - - /** - * @dataProvider dataSetIconInvalid - * @param mixed $icon - * - * @expectedException \InvalidArgumentException - */ - public function testSetIconInvalid($icon) { - $this->notification->setIcon($icon); - } - public function testCreateAction() { $action = $this->notification->createAction(); $this->assertInstanceOf('OC\Notification\IAction', $action); -- GitLab From fc296aad5d2db3b95958bff23dead592332655c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 16:29:01 +0100 Subject: [PATCH 046/344] Add occ command to create a new calendar --- apps/dav/appinfo/register_command.php | 2 ++ apps/dav/command/createcalendar.php | 52 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 apps/dav/command/createcalendar.php diff --git a/apps/dav/appinfo/register_command.php b/apps/dav/appinfo/register_command.php index c996dd44063..7d57b944fb2 100644 --- a/apps/dav/appinfo/register_command.php +++ b/apps/dav/appinfo/register_command.php @@ -1,8 +1,10 @@ getDatabaseConnection(); $userManager = OC::$server->getUserManager(); /** @var Symfony\Component\Console\Application $application */ $application->add(new CreateAddressBook($userManager, $dbConnection)); +$application->add(new CreateCalendar($userManager, $dbConnection)); diff --git a/apps/dav/command/createcalendar.php b/apps/dav/command/createcalendar.php new file mode 100644 index 00000000000..da4f248e51d --- /dev/null +++ b/apps/dav/command/createcalendar.php @@ -0,0 +1,52 @@ +userManager = $userManager; + $this->dbConnection = $dbConnection; + } + + protected function configure() { + $this + ->setName('dav:create-calendar') + ->setDescription('Create a dav calendar') + ->addArgument('user', + InputArgument::REQUIRED, + 'User for whom the calendar will be created') + ->addArgument('name', + InputArgument::REQUIRED, + 'Name of the calendar'); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $user = $input->getArgument('user'); + if (!$this->userManager->userExists($user)) { + throw new \InvalidArgumentException("User <$user> in unknown."); + } + $name = $input->getArgument('name'); + $caldav = new CalDavBackend($this->dbConnection); + $caldav->createCalendar("principals/$user", $name, []); + } +} -- GitLab From 6ffd042a64b7d75fc1ca1939a43de3fd107b1b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 16:20:42 +0100 Subject: [PATCH 047/344] fixes #20538 --- lib/private/log/owncloud.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/private/log/owncloud.php b/lib/private/log/owncloud.php index 1af989588d1..721bc6002fa 100644 --- a/lib/private/log/owncloud.php +++ b/lib/private/log/owncloud.php @@ -66,13 +66,16 @@ class OC_Log_Owncloud { // default to ISO8601 $format = $config->getValue('logdateformat', 'c'); - $logtimezone = $config->getValue( "logtimezone", 'UTC' ); + $logTimeZone = $config->getValue( "logtimezone", 'UTC' ); try { - $timezone = new DateTimeZone($logtimezone); + $timezone = new DateTimeZone($logTimeZone); } catch (Exception $e) { $timezone = new DateTimeZone('UTC'); } $time = DateTime::createFromFormat("U.u", microtime(true), $timezone); + if ($time === false) { + $time = new DateTime(null, $timezone); + } $request = \OC::$server->getRequest(); $reqId = $request->getId(); $remoteAddr = $request->getRemoteAddress(); -- GitLab From 27849077822cf85647bc79262c4b72b9591d43fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 16:36:12 +0100 Subject: [PATCH 048/344] password_policy is a shipped app --- core/shipped.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/shipped.json b/core/shipped.json index 49a649f3c9e..cd1fca4d9fe 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -31,7 +31,8 @@ "user_external", "user_ldap", "user_shibboleth", - "windows_network_drive" + "windows_network_drive", + "password_policy" ], "alwaysEnabled": [ "files", -- GitLab From a0b649442cadec1f9b1d97bcd6b0c3e1289671d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 17:46:17 +0100 Subject: [PATCH 049/344] components was not written to the database --- apps/dav/lib/caldav/caldavbackend.php | 1 + apps/dav/tests/unit/caldav/caldavbackendtest.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php index 4dcd1bed3de..19bbc6cb93d 100644 --- a/apps/dav/lib/caldav/caldavbackend.php +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -212,6 +212,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'uri' => $query->createNamedParameter($values['uri']), 'synctoken' => $query->createNamedParameter($values['synctoken']), 'transparent' => $query->createNamedParameter($values['transparent']), + 'components' => $query->createNamedParameter($values['components']), ]) ->execute(); } diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php index 5e3d4288aa7..fdd76f90213 100644 --- a/apps/dav/tests/unit/caldav/caldavbackendtest.php +++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php @@ -23,6 +23,7 @@ namespace Tests\Connector\Sabre; use DateTime; use DateTimeZone; use OCA\DAV\CalDAV\CalDavBackend; +use Sabre\CalDAV\Property\SupportedCalendarComponentSet; use Sabre\DAV\Property\Href; use Sabre\DAV\PropPatch; use Test\TestCase; @@ -252,6 +253,9 @@ EOD; $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); $this->assertEquals(1, count($calendars)); $this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']); + /** @var SupportedCalendarComponentSet $components */ + $components = $calendars[0]['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']; + $this->assertEquals(['VEVENT','VTODO'], $components->getValue()); $this->assertEquals('Example', $calendars[0]['uri']); $calendarId = $calendars[0]['id']; -- GitLab From e4568234a5c2e7f597d511e8fd1cbafa409bf29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 16 Nov 2015 21:01:27 +0100 Subject: [PATCH 050/344] Use uri as displayname --- apps/dav/lib/caldav/caldavbackend.php | 26 +++++-------------- .../tests/unit/caldav/caldavbackendtest.php | 7 ++++- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php index 19bbc6cb93d..08a2a70c56d 100644 --- a/apps/dav/lib/caldav/caldavbackend.php +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -169,19 +169,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return void */ function createCalendar($principalUri, $calendarUri, array $properties) { - $fieldNames = [ - 'principaluri', - 'uri', - 'synctoken', - 'transparent', - 'components' - ]; $values = [ 'principaluri' => $principalUri, 'uri' => $calendarUri, 'synctoken' => 1, 'transparent' => 0, - 'components' => 'VEVENT,VTODO' + 'components' => 'VEVENT,VTODO', + 'displayname' => $calendarUri ]; // Default value @@ -199,22 +193,16 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription foreach($this->propertyMap as $xmlName=>$dbName) { if (isset($properties[$xmlName])) { - $values[$dbName] = $properties[$xmlName]; - $fieldNames[] = $dbName; } } $query = $this->db->getQueryBuilder(); - $query->insert('calendars') - ->values([ - 'principaluri' => $query->createNamedParameter($values['principaluri']), - 'uri' => $query->createNamedParameter($values['uri']), - 'synctoken' => $query->createNamedParameter($values['synctoken']), - 'transparent' => $query->createNamedParameter($values['transparent']), - 'components' => $query->createNamedParameter($values['components']), - ]) - ->execute(); + $query->insert('calendars'); + foreach($values as $column => $value) { + $query->setValue($column, $query->createNamedParameter($value)); + } + $query->execute(); } /** diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php index fdd76f90213..258c5627ad9 100644 --- a/apps/dav/tests/unit/caldav/caldavbackendtest.php +++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php @@ -249,14 +249,19 @@ EOD; } private function createTestCalendar() { - $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []); + $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', [ + '{http://apple.com/ns/ical/}calendar-color' => '#1C4587FF' + ]); $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); $this->assertEquals(1, count($calendars)); $this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']); /** @var SupportedCalendarComponentSet $components */ $components = $calendars[0]['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']; $this->assertEquals(['VEVENT','VTODO'], $components->getValue()); + $color = $calendars[0]['{http://apple.com/ns/ical/}calendar-color']; + $this->assertEquals('#1C4587FF', $color); $this->assertEquals('Example', $calendars[0]['uri']); + $this->assertEquals('Example', $calendars[0]['{DAV:}displayname']); $calendarId = $calendars[0]['id']; return $calendarId; -- GitLab From daa388ce8d8ea653d3cae2e016cabd266d19d674 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 16 Nov 2015 20:57:41 +0100 Subject: [PATCH 051/344] Move index.php from files to AppFramework 1. Allows it to use the more secure CSP rules of the AppFramework. 2. Adds some unit tests. --- apps/files/appinfo/app.php | 4 +- apps/files/appinfo/routes.php | 7 +- apps/files/controller/viewcontroller.php | 224 ++++++++++++++++ apps/files/index.php | 161 ----------- .../tests/controller/ViewControllerTest.php | 250 ++++++++++++++++++ .../dependencyinjection/dicontainer.php | 4 + tests/lib/helper.php | 28 +- tests/lib/urlgenerator.php | 10 +- 8 files changed, 511 insertions(+), 177 deletions(-) create mode 100644 apps/files/controller/viewcontroller.php delete mode 100644 apps/files/index.php create mode 100644 apps/files/tests/controller/ViewControllerTest.php diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index 40b194ab882..c752b5e7d72 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -25,12 +25,14 @@ */ \OCP\App::registerAdmin('files', 'admin'); + \OC::$server->getNavigationManager()->add(function () { + $urlGenerator = \OC::$server->getURLGenerator(); $l = \OC::$server->getL10N('files'); return [ 'id' => 'files_index', 'order' => 0, - 'href' => \OCP\Util::linkTo('files', 'index.php'), + 'href' => $urlGenerator->linkToRoute('files.view.index'), 'icon' => \OCP\Util::imagePath('core', 'places/files.svg'), 'name' => $l->t('Files'), ]; diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php index d52dfaab21c..2bb913c30a6 100644 --- a/apps/files/appinfo/routes.php +++ b/apps/files/appinfo/routes.php @@ -48,14 +48,17 @@ $application->registerRoutes( 'verb' => 'GET', 'requirements' => array('tagName' => '.+'), ), + [ + 'name' => 'view#index', + 'url' => '/', + 'verb' => 'GET', + ], ) ) ); /** @var $this \OC\Route\Router */ -$this->create('files_index', '/') - ->actionInclude('files/index.php'); $this->create('files_ajax_delete', 'ajax/delete.php') ->actionInclude('files/ajax/delete.php'); $this->create('files_ajax_download', 'ajax/download.php') diff --git a/apps/files/controller/viewcontroller.php b/apps/files/controller/viewcontroller.php new file mode 100644 index 00000000000..c274680e525 --- /dev/null +++ b/apps/files/controller/viewcontroller.php @@ -0,0 +1,224 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Files\Controller; + +use OC\AppFramework\Http\Request; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\IL10N; +use OCP\INavigationManager; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\IConfig; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Class ViewController + * + * @package OCA\Files\Controller + */ +class ViewController extends Controller { + /** @var string */ + protected $appName; + /** @var IRequest */ + protected $request; + /** @var IURLGenerator */ + protected $urlGenerator; + /** @var INavigationManager */ + protected $navigationManager; + /** @var IL10N */ + protected $l10n; + /** @var IConfig */ + protected $config; + /** @var EventDispatcherInterface */ + protected $eventDispatcher; + + /** + * @param string $appName + * @param IRequest $request + * @param IURLGenerator $urlGenerator + * @param INavigationManager $navigationManager + * @param IL10N $l10n + * @param IConfig $config + * @param EventDispatcherInterface $eventDispatcherInterface + */ + public function __construct($appName, + IRequest $request, + IURLGenerator $urlGenerator, + INavigationManager $navigationManager, + IL10N $l10n, + IConfig $config, + EventDispatcherInterface $eventDispatcherInterface) { + parent::__construct($appName, $request); + $this->appName = $appName; + $this->request = $request; + $this->urlGenerator = $urlGenerator; + $this->navigationManager = $navigationManager; + $this->l10n = $l10n; + $this->config = $config; + $this->eventDispatcher = $eventDispatcherInterface; + } + + /** + * @param string $appName + * @param string $scriptName + * @return string + */ + protected function renderScript($appName, $scriptName) { + $content = ''; + $appPath = \OC_App::getAppPath($appName); + $scriptPath = $appPath . '/' . $scriptName; + if (file_exists($scriptPath)) { + // TODO: sanitize path / script name ? + ob_start(); + include $scriptPath; + $content = ob_get_contents(); + @ob_end_clean(); + } + return $content; + } + + /** + * FIXME: Replace with non static code + * + * @return array + * @throws \OCP\Files\NotFoundException + */ + protected function getStorageInfo() { + $dirInfo = \OC\Files\Filesystem::getFileInfo('/', false); + return \OC_Helper::getStorageInfo('/', $dirInfo); + } + + /** + * @NoCSRFRequired + * @NoAdminRequired + * + * @param string $dir + * @param string $view + * @return TemplateResponse + * @throws \OCP\Files\NotFoundException + */ + public function index($dir = '', $view = '') { + // Load the files we need + \OCP\Util::addStyle('files', 'files'); + \OCP\Util::addStyle('files', 'upload'); + \OCP\Util::addStyle('files', 'mobile'); + \OCP\Util::addscript('files', 'app'); + \OCP\Util::addscript('files', 'file-upload'); + \OCP\Util::addscript('files', 'newfilemenu'); + \OCP\Util::addscript('files', 'jquery.iframe-transport'); + \OCP\Util::addscript('files', 'jquery.fileupload'); + \OCP\Util::addscript('files', 'jquery-visibility'); + \OCP\Util::addscript('files', 'fileinfomodel'); + \OCP\Util::addscript('files', 'filesummary'); + \OCP\Util::addscript('files', 'breadcrumb'); + \OCP\Util::addscript('files', 'filelist'); + \OCP\Util::addscript('files', 'search'); + + \OCP\Util::addScript('files', 'favoritesfilelist'); + \OCP\Util::addScript('files', 'tagsplugin'); + \OCP\Util::addScript('files', 'favoritesplugin'); + + \OCP\Util::addScript('files', 'detailfileinfoview'); + \OCP\Util::addScript('files', 'detailtabview'); + \OCP\Util::addScript('files', 'mainfileinfodetailview'); + \OCP\Util::addScript('files', 'detailsview'); + \OCP\Util::addStyle('files', 'detailsView'); + + \OC_Util::addVendorScript('core', 'handlebars/handlebars'); + + \OCP\Util::addscript('files', 'fileactions'); + \OCP\Util::addscript('files', 'fileactionsmenu'); + \OCP\Util::addscript('files', 'files'); + \OCP\Util::addscript('files', 'keyboardshortcuts'); + \OCP\Util::addscript('files', 'navigation'); + + // if IE8 and "?dir=path&view=someview" was specified, reformat the URL to use a hash like "#?dir=path&view=someview" + $isIE8 = $this->request->isUserAgent([Request::USER_AGENT_IE_8]); + if ($isIE8 && ($dir !== '' || $view !== '')) { + $dir = !empty($dir) ? $dir : '/'; + $view = !empty($view) ? $view : 'files'; + $hash = '#?dir=' . \OCP\Util::encodePath($dir); + if ($view !== 'files') { + $hash .= '&view=' . urlencode($view); + } + return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index') . $hash); + } + + // mostly for the home storage's free space + // FIXME: Make non static + $storageInfo = $this->getStorageInfo(); + + $nav = new \OCP\Template('files', 'appnavigation', ''); + + \OCA\Files\App::getNavigationManager()->add( + [ + 'id' => 'favorites', + 'appname' => 'files', + 'script' => 'simplelist.php', + 'order' => 5, + 'name' => $this->l10n->t('Favorites') + ] + ); + + $navItems = \OCA\Files\App::getNavigationManager()->getAll(); + usort($navItems, function($item1, $item2) { + return $item1['order'] - $item2['order']; + }); + $nav->assign('navigationItems', $navItems); + + $contentItems = []; + + // render the container content for every navigation item + foreach ($navItems as $item) { + $content = ''; + if (isset($item['script'])) { + $content = $this->renderScript($item['appname'], $item['script']); + } + $contentItem = []; + $contentItem['id'] = $item['id']; + $contentItem['content'] = $content; + $contentItems[] = $contentItem; + } + + $this->eventDispatcher->dispatch('OCA\Files::loadAdditionalScripts'); + + $params = []; + $params['usedSpacePercent'] = (int)$storageInfo['relative']; + $params['owner'] = $storageInfo['owner']; + $params['ownerDisplayName'] = $storageInfo['ownerDisplayName']; + $params['isPublic'] = false; + $params['mailNotificationEnabled'] = $this->config->getAppValue('core', 'shareapi_allow_mail_notification', 'no'); + $params['mailPublicNotificationEnabled'] = $this->config->getAppValue('core', 'shareapi_allow_public_notification', 'no'); + $params['allowShareWithLink'] = $this->config->getAppValue('core', 'shareapi_allow_links', 'yes'); + $params['appNavigation'] = $nav; + $params['appContents'] = $contentItems; + $this->navigationManager->setActiveEntry('files_index'); + + return new TemplateResponse( + $this->appName, + 'index', + $params + ); + } +} diff --git a/apps/files/index.php b/apps/files/index.php deleted file mode 100644 index cc007ebdb07..00000000000 --- a/apps/files/index.php +++ /dev/null @@ -1,161 +0,0 @@ - - * @author Frank Karlitschek - * @author Jakob Sack - * @author Jan-Christoph Borchardt - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Morris Jobke - * @author Robin Appelman - * @author Roman Geber - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ - -// Check if we are a user -OCP\User::checkLoggedIn(); - -// Load the files we need -OCP\Util::addStyle('files', 'files'); -OCP\Util::addStyle('files', 'upload'); -OCP\Util::addStyle('files', 'mobile'); -OCP\Util::addscript('files', 'app'); -OCP\Util::addscript('files', 'file-upload'); -OCP\Util::addscript('files', 'newfilemenu'); -OCP\Util::addscript('files', 'jquery.iframe-transport'); -OCP\Util::addscript('files', 'jquery.fileupload'); -OCP\Util::addscript('files', 'jquery-visibility'); -OCP\Util::addscript('files', 'fileinfomodel'); -OCP\Util::addscript('files', 'filesummary'); -OCP\Util::addscript('files', 'breadcrumb'); -OCP\Util::addscript('files', 'filelist'); -OCP\Util::addscript('files', 'search'); - -\OCP\Util::addScript('files', 'favoritesfilelist'); -\OCP\Util::addScript('files', 'tagsplugin'); -\OCP\Util::addScript('files', 'favoritesplugin'); - -\OCP\Util::addScript('files', 'detailfileinfoview'); -\OCP\Util::addScript('files', 'detailtabview'); -\OCP\Util::addScript('files', 'mainfileinfodetailview'); -\OCP\Util::addScript('files', 'detailsview'); -\OCP\Util::addStyle('files', 'detailsView'); - -\OC_Util::addVendorScript('core', 'handlebars/handlebars'); - -OCP\App::setActiveNavigationEntry('files_index'); - -$l = \OC::$server->getL10N('files'); - -$isIE8 = false; -preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches); -if (count($matches) > 0 && $matches[1] <= 9) { - $isIE8 = true; -} - -// if IE8 and "?dir=path&view=someview" was specified, reformat the URL to use a hash like "#?dir=path&view=someview" -if ($isIE8 && (isset($_GET['dir']) || isset($_GET['view']))) { - $hash = '#?'; - $dir = isset($_GET['dir']) ? $_GET['dir'] : '/'; - $view = isset($_GET['view']) ? $_GET['view'] : 'files'; - $hash = '#?dir=' . \OCP\Util::encodePath($dir); - if ($view !== 'files') { - $hash .= '&view=' . urlencode($view); - } - header('Location: ' . OCP\Util::linkTo('files', 'index.php') . $hash); - exit(); -} - -$user = OC_User::getUser(); - -$config = \OC::$server->getConfig(); - -// mostly for the home storage's free space -$dirInfo = \OC\Files\Filesystem::getFileInfo('/', false); -$storageInfo=OC_Helper::getStorageInfo('/', $dirInfo); - -$nav = new OCP\Template('files', 'appnavigation', ''); - -function sortNavigationItems($item1, $item2) { - return $item1['order'] - $item2['order']; -} - -\OCA\Files\App::getNavigationManager()->add( - array( - 'id' => 'favorites', - 'appname' => 'files', - 'script' => 'simplelist.php', - 'order' => 5, - 'name' => $l->t('Favorites') - ) -); - -$navItems = \OCA\Files\App::getNavigationManager()->getAll(); -usort($navItems, 'sortNavigationItems'); -$nav->assign('navigationItems', $navItems); - -$contentItems = array(); - -function renderScript($appName, $scriptName) { - $content = ''; - $appPath = OC_App::getAppPath($appName); - $scriptPath = $appPath . '/' . $scriptName; - if (file_exists($scriptPath)) { - // TODO: sanitize path / script name ? - ob_start(); - include $scriptPath; - $content = ob_get_contents(); - @ob_end_clean(); - } - return $content; -} - -// render the container content for every navigation item -foreach ($navItems as $item) { - $content = ''; - if (isset($item['script'])) { - $content = renderScript($item['appname'], $item['script']); - } - $contentItem = array(); - $contentItem['id'] = $item['id']; - $contentItem['content'] = $content; - $contentItems[] = $contentItem; -} - -OCP\Util::addscript('files', 'fileactions'); -OCP\Util::addscript('files', 'fileactionsmenu'); -OCP\Util::addscript('files', 'files'); -OCP\Util::addscript('files', 'navigation'); -OCP\Util::addscript('files', 'keyboardshortcuts'); - -\OC::$server->getEventDispatcher()->dispatch('OCA\Files::loadAdditionalScripts'); - -$tmpl = new OCP\Template('files', 'index', 'user'); -$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']); -$tmpl->assign('owner', $storageInfo['owner']); -$tmpl->assign('ownerDisplayName', $storageInfo['ownerDisplayName']); -$tmpl->assign('isPublic', false); -$tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_mail_notification', 'no')); -$tmpl->assign("mailPublicNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_public_notification', 'no')); -$tmpl->assign("allowShareWithLink", $config->getAppValue('core', 'shareapi_allow_links', 'yes')); -$tmpl->assign('appNavigation', $nav); -$tmpl->assign('appContents', $contentItems); - -$tmpl->printPage(); diff --git a/apps/files/tests/controller/ViewControllerTest.php b/apps/files/tests/controller/ViewControllerTest.php new file mode 100644 index 00000000000..028dfce8c58 --- /dev/null +++ b/apps/files/tests/controller/ViewControllerTest.php @@ -0,0 +1,250 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Files\Tests\Controller; + +use OCA\Files\Controller\ViewController; +use OCP\AppFramework\Http; +use OCP\Template; +use Test\TestCase; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\INavigationManager; +use OCP\IL10N; +use OCP\IConfig; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Class ViewControllerTest + * + * @package OCA\Files\Tests\Controller + */ +class ViewControllerTest extends TestCase { + /** @var IRequest */ + private $request; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var INavigationManager */ + private $navigationManager; + /** @var IL10N */ + private $l10n; + /** @var IConfig */ + private $config; + /** @var EventDispatcherInterface */ + private $eventDispatcher; + /** @var ViewController */ + private $viewController; + + public function setUp() { + parent::setUp(); + $this->request = $this->getMock('\OCP\IRequest'); + $this->urlGenerator = $this->getMock('\OCP\IURLGenerator'); + $this->navigationManager = $this->getMock('\OCP\INavigationManager'); + $this->l10n = $this->getMock('\OCP\IL10N'); + $this->config = $this->getMock('\OCP\IConfig'); + $this->eventDispatcher = $this->getMock('\Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController') + ->setConstructorArgs([ + 'files', + $this->request, + $this->urlGenerator, + $this->navigationManager, + $this->l10n, + $this->config, + $this->eventDispatcher + ]) + ->setMethods([ + 'getStorageInfo', + 'renderScript' + ]) + ->getMock(); + } + + public function testIndexWithIE8RedirectAndDirDefined() { + $this->request + ->expects($this->once()) + ->method('isUserAgent') + ->with(['/MSIE 8.0/']) + ->will($this->returnValue(true)); + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRoute') + ->with('files.view.index') + ->will($this->returnValue('/apps/files/')); + + $expected = new Http\RedirectResponse('/apps/files/#?dir=MyDir'); + $this->assertEquals($expected, $this->viewController->index('MyDir')); + } + + public function testIndexWithIE8RedirectAndViewDefined() { + $this->request + ->expects($this->once()) + ->method('isUserAgent') + ->with(['/MSIE 8.0/']) + ->will($this->returnValue(true)); + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRoute') + ->with('files.view.index') + ->will($this->returnValue('/apps/files/')); + + $expected = new Http\RedirectResponse('/apps/files/#?dir=/&view=MyView'); + $this->assertEquals($expected, $this->viewController->index('', 'MyView')); + } + + public function testIndexWithIE8RedirectAndViewAndDirDefined() { + $this->request + ->expects($this->once()) + ->method('isUserAgent') + ->with(['/MSIE 8.0/']) + ->will($this->returnValue(true)); + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRoute') + ->with('files.view.index') + ->will($this->returnValue('/apps/files/')); + + $expected = new RedirectResponse('/apps/files/#?dir=MyDir&view=MyView'); + $this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView')); + } + + public function testIndexWithRegularBrowser() { + $this->request + ->expects($this->once()) + ->method('isUserAgent') + ->with(['/MSIE 8.0/']) + ->will($this->returnValue(false)); + $this->viewController + ->expects($this->once()) + ->method('getStorageInfo') + ->will($this->returnValue([ + 'relative' => 123, + 'owner' => 'MyName', + 'ownerDisplayName' => 'MyDisplayName', + ])); + + $this->config + ->expects($this->any()) + ->method('getAppValue') + ->will($this->returnArgument(2)); + + $nav = new Template('files', 'appnavigation'); + $nav->assign('navigationItems', [ + 0 => [ + 'id' => 'files', + 'appname' => 'files', + 'script' => 'list.php', + 'order' => 0, + 'name' => new \OC_L10N_String(new \OC_L10N('files'), 'All files', []), + 'active' => false, + 'icon' => '', + ], + 1 => [ + 'id' => 'favorites', + 'appname' => 'files', + 'script' => 'simplelist.php', + 'order' => 5, + 'name' => null, + 'active' => false, + 'icon' => '', + ], + 2 => [ + 'id' => 'sharingin', + 'appname' => 'files_sharing', + 'script' => 'list.php', + 'order' => 10, + 'name' => new \OC_L10N_String(new \OC_L10N('files_sharing'), 'Shared with you', []), + 'active' => false, + 'icon' => '', + ], + 3 => [ + 'id' => 'sharingout', + 'appname' => 'files_sharing', + 'script' => 'list.php', + 'order' => 15, + 'name' => new \OC_L10N_String(new \OC_L10N('files_sharing'), 'Shared with others', []), + 'active' => false, + 'icon' => '', + ], + 4 => [ + 'id' => 'sharinglinks', + 'appname' => 'files_sharing', + 'script' => 'list.php', + 'order' => 20, + 'name' => new \OC_L10N_String(new \OC_L10N('files_sharing'), 'Shared by link', []), + 'active' => false, + 'icon' => '', + ], + 5 => [ + 'id' => 'trashbin', + 'appname' => 'files_trashbin', + 'script' => 'list.php', + 'order' => 50, + 'name' => new \OC_L10N_String(new \OC_L10N('files_trashbin'), 'Deleted files', []), + 'active' => false, + 'icon' => '', + ], + ]); + + $expected = new Http\TemplateResponse( + 'files', + 'index', + [ + 'usedSpacePercent' => 123, + 'owner' => 'MyName', + 'ownerDisplayName' => 'MyDisplayName', + 'isPublic' => false, + 'mailNotificationEnabled' => 'no', + 'mailPublicNotificationEnabled' => 'no', + 'allowShareWithLink' => 'yes', + 'appNavigation' => $nav, + 'appContents' => [ + 0 => [ + 'id' => 'files', + 'content' => null, + ], + 1 => [ + 'id' => 'favorites', + 'content' => null, + ], + 2 => [ + 'id' => 'sharingin', + 'content' => null, + ], + 3 => [ + 'id' => 'sharingout', + 'content' => null, + ], + 4 => [ + 'id' => 'sharinglinks', + 'content' => null, + ], + 5 => [ + 'id' => 'trashbin', + 'content' => null, + ], + ], + ] + ); + $this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView')); + } +} diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index b0be4045541..a32d32fefc5 100644 --- a/lib/private/appframework/dependencyinjection/dicontainer.php +++ b/lib/private/appframework/dependencyinjection/dicontainer.php @@ -226,6 +226,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer(); }); + $this->registerService('Symfony\Component\EventDispatcher\EventDispatcherInterface', function ($c) { + return $this->getServer()->getEventDispatcher(); + }); + $this->registerService('OCP\\AppFramework\\IAppContainer', function ($c) { return $c; }); diff --git a/tests/lib/helper.php b/tests/lib/helper.php index bd527de160d..ca3e0e46d82 100644 --- a/tests/lib/helper.php +++ b/tests/lib/helper.php @@ -353,18 +353,24 @@ class Test_Helper extends \Test\TestCase { $this->assertEquals($expectedResult, $result); } + /** + * @return array + */ public function provideDocRootAppUrlParts() { return array( - array('files', 'index.php', array(), '/index.php/apps/files'), - array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php/apps/files?trut=trat&dut=dat'), + array('files', 'ajax/list.php', array(), '/index.php/apps/files/ajax/list.php'), + array('files', 'ajax/list.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php/apps/files/ajax/list.php?trut=trat&dut=dat'), array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php?trut=trat&dut=dat'), ); } + /** + * @return array + */ public function provideSubDirAppUrlParts() { return array( - array('files', 'index.php', array(), '/owncloud/index.php/apps/files'), - array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php/apps/files?trut=trat&dut=dat'), + array('files', 'ajax/list.php', array(), '/owncloud/index.php/apps/files/ajax/list.php'), + array('files', 'ajax/list.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php/apps/files/ajax/list.php?trut=trat&dut=dat'), array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php?trut=trat&dut=dat'), ); } @@ -393,18 +399,24 @@ class Test_Helper extends \Test\TestCase { $this->assertEquals($expectedResult, $result); } + /** + * @return array + */ public function provideDocRootAppAbsoluteUrlParts() { return array( - array('files', 'index.php', array(), 'http://localhost/index.php/apps/files'), - array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/index.php/apps/files?trut=trat&dut=dat'), + array('files', 'ajax/list.php', array(), 'http://localhost/index.php/apps/files/ajax/list.php'), + array('files', 'ajax/list.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/index.php/apps/files/ajax/list.php?trut=trat&dut=dat'), array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/index.php?trut=trat&dut=dat'), ); } + /** + * @return array + */ public function provideSubDirAppAbsoluteUrlParts() { return array( - array('files', 'index.php', array(), 'http://localhost/owncloud/index.php/apps/files'), - array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/owncloud/index.php/apps/files?trut=trat&dut=dat'), + array('files', 'ajax/list.php', array(), 'http://localhost/owncloud/index.php/apps/files/ajax/list.php'), + array('files', 'ajax/list.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/owncloud/index.php/apps/files/ajax/list.php?trut=trat&dut=dat'), array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/owncloud/index.php?trut=trat&dut=dat'), ); } diff --git a/tests/lib/urlgenerator.php b/tests/lib/urlgenerator.php index 60e1a86f16a..a5ab483109f 100644 --- a/tests/lib/urlgenerator.php +++ b/tests/lib/urlgenerator.php @@ -53,23 +53,23 @@ class Test_Urlgenerator extends \Test\TestCase { public function provideRoutes() { return array( - array('files_index', 'http://localhost/owncloud/index.php/apps/files/'), + array('files_ajax_list', 'http://localhost/owncloud/index.php/apps/files/ajax/list.php'), array('core_ajax_preview', 'http://localhost/owncloud/index.php/core/preview.png'), ); } public function provideDocRootAppUrlParts() { return array( - array('files', 'index.php', array(), '/index.php/apps/files'), - array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php/apps/files?trut=trat&dut=dat'), + array('files', 'ajax/list.php', array(), '/index.php/apps/files/ajax/list.php'), + array('files', 'ajax/list.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php/apps/files/ajax/list.php?trut=trat&dut=dat'), array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php?trut=trat&dut=dat'), ); } public function provideSubDirAppUrlParts() { return array( - array('files', 'index.php', array(), '/owncloud/index.php/apps/files'), - array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php/apps/files?trut=trat&dut=dat'), + array('files', 'ajax/list.php', array(), '/owncloud/index.php/apps/files/ajax/list.php'), + array('files', 'ajax/list.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php/apps/files/ajax/list.php?trut=trat&dut=dat'), array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php?trut=trat&dut=dat'), ); } -- GitLab From d49fc9a5fcb993307ff7ef188fff3da8a3d03c69 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 16 Nov 2015 21:51:10 +0100 Subject: [PATCH 052/344] fix ip detection for swift-ceph --- apps/files_external/tests/env/start-swift-ceph.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_external/tests/env/start-swift-ceph.sh b/apps/files_external/tests/env/start-swift-ceph.sh index a8305eee5a2..ea16e167af9 100755 --- a/apps/files_external/tests/env/start-swift-ceph.sh +++ b/apps/files_external/tests/env/start-swift-ceph.sh @@ -48,7 +48,7 @@ container=`docker run -d \ -e KEYSTONE_SERVICE=${service} \ ${docker_image}` -host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` +host=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container` echo "${docker_image} container: $container" -- GitLab From 6dcaac7e2c68ed55c59e4aa40e9cca3a79712f84 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 16 Nov 2015 22:24:53 +0100 Subject: [PATCH 053/344] Return empty list if group does not have subadmins Instead of throwing an error just return an empty list. Since that is actually what it is. Fixes #19789 --- apps/provisioning_api/lib/groups.php | 8 +------- apps/provisioning_api/tests/groupstest.php | 5 ++--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/apps/provisioning_api/lib/groups.php b/apps/provisioning_api/lib/groups.php index 7c35caca5fd..7a6e6150782 100644 --- a/apps/provisioning_api/lib/groups.php +++ b/apps/provisioning_api/lib/groups.php @@ -176,14 +176,8 @@ class Groups{ foreach ($subadmins as $user) { $uids[] = $user->getUID(); } - $subadmins = $uids; - // Go - if(!$subadmins) { - return new OC_OCS_Result(null, 102, 'Unknown error occured'); - } else { - return new OC_OCS_Result($subadmins); - } + return new OC_OCS_Result($uids); } } diff --git a/apps/provisioning_api/tests/groupstest.php b/apps/provisioning_api/tests/groupstest.php index 7d4beb6a368..d37f4412e20 100644 --- a/apps/provisioning_api/tests/groupstest.php +++ b/apps/provisioning_api/tests/groupstest.php @@ -308,9 +308,8 @@ class GroupsTest extends \Test\TestCase { ]); $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); - $this->assertEquals('Unknown error occured', $result->getMeta()['message']); + $this->assertTrue($result->succeeded()); + $this->assertEquals([], $result->getData()); } public function testAddGroupEmptyGroup() { -- GitLab From 56f44a457c74cb5df0d5e950e67deac99cae7b41 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Tue, 17 Nov 2015 01:55:08 -0500 Subject: [PATCH 054/344] [tx-robot] updated from transifex --- core/l10n/ru.js | 2 ++ core/l10n/ru.json | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/l10n/ru.js b/core/l10n/ru.js index 2df910a6aa4..39302e9a18e 100644 --- a/core/l10n/ru.js +++ b/core/l10n/ru.js @@ -177,6 +177,7 @@ OC.L10N.register( "Hello {name}" : "Здравствуйте {name}", "_download %n file_::_download %n files_" : ["скачать %n файл","скачать %n файла","скачать %n файлов","скачать %n файлов"], "{version} is available. Get more information on how to update." : "Доступна версия {version}. Получить дополнительную информацию о порядке обновления.", + "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Идет обновление. Покидая эту страницу, вы можете прервать процесс обновления.", "Updating {productName} to version {version}, this may take a while." : "Идет обновление {productName} до версии {version}, пожалуйста, подождите.", "An error occurred." : "Произошла ошибка.", "Please reload the page." : "Обновите страницу.", @@ -268,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.", "Thank you for your patience." : "Спасибо за терпение.", "You are accessing the server from an untrusted domain." : "Вы пытаетесь получить доступ к серверу с неподтверждённого домена.", + "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." : "Пожалуйста, обратитесь к администратору. Если вы являетесь администратором этого экземпляра, настроить параметры \"trusted_domains\" можно в config/config.php. Пример настройки можно найти в config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимости от конфигурации, как администратор вы можете также внести домен в доверенные с помощью кнопки ниже.", "Add \"%s\" as trusted domain" : "Добавить \"%s\" как доверенный домен", "App update required" : "Требуется обновление приложения", diff --git a/core/l10n/ru.json b/core/l10n/ru.json index 66d3b463899..a24ee0831a0 100644 --- a/core/l10n/ru.json +++ b/core/l10n/ru.json @@ -175,6 +175,7 @@ "Hello {name}" : "Здравствуйте {name}", "_download %n file_::_download %n files_" : ["скачать %n файл","скачать %n файла","скачать %n файлов","скачать %n файлов"], "{version} is available. Get more information on how to update." : "Доступна версия {version}. Получить дополнительную информацию о порядке обновления.", + "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Идет обновление. Покидая эту страницу, вы можете прервать процесс обновления.", "Updating {productName} to version {version}, this may take a while." : "Идет обновление {productName} до версии {version}, пожалуйста, подождите.", "An error occurred." : "Произошла ошибка.", "Please reload the page." : "Обновите страницу.", @@ -266,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.", "Thank you for your patience." : "Спасибо за терпение.", "You are accessing the server from an untrusted domain." : "Вы пытаетесь получить доступ к серверу с неподтверждённого домена.", + "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." : "Пожалуйста, обратитесь к администратору. Если вы являетесь администратором этого экземпляра, настроить параметры \"trusted_domains\" можно в config/config.php. Пример настройки можно найти в config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "В зависимости от конфигурации, как администратор вы можете также внести домен в доверенные с помощью кнопки ниже.", "Add \"%s\" as trusted domain" : "Добавить \"%s\" как доверенный домен", "App update required" : "Требуется обновление приложения", -- GitLab From 2fde6a77d7b586a5f51fdc9a93da1f3961e696e3 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 17 Nov 2015 09:26:13 +0100 Subject: [PATCH 055/344] Add tests for the "return $this" and fix it on the new method --- lib/private/notification/action.php | 4 +- lib/private/notification/iaction.php | 1 + tests/lib/notification/actiontest.php | 52 ++++++++++++++++++--- tests/lib/notification/notificationtest.php | 26 +++++------ 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/lib/private/notification/action.php b/lib/private/notification/action.php index 958b085b38e..8eade697025 100644 --- a/lib/private/notification/action.php +++ b/lib/private/notification/action.php @@ -50,7 +50,7 @@ class Action implements IAction { $this->labelParsed = ''; $this->link = ''; $this->requestType = ''; - $this->icon = ''; + $this->primary = false; } /** @@ -99,6 +99,7 @@ class Action implements IAction { /** * @param $primary bool + * @return $this * @throws \InvalidArgumentException if $primary is invalid * @since 9.0.0 */ @@ -108,6 +109,7 @@ class Action implements IAction { } $this->primary = $primary; + return $this; } /** diff --git a/lib/private/notification/iaction.php b/lib/private/notification/iaction.php index 4aed2e92517..f7366dd4388 100644 --- a/lib/private/notification/iaction.php +++ b/lib/private/notification/iaction.php @@ -62,6 +62,7 @@ interface IAction { /** * @param $primary bool + * @return $this * @throws \InvalidArgumentException if $primary is invalid * @since 9.0.0 */ diff --git a/tests/lib/notification/actiontest.php b/tests/lib/notification/actiontest.php index a6157d6c56e..0044df82cd1 100644 --- a/tests/lib/notification/actiontest.php +++ b/tests/lib/notification/actiontest.php @@ -49,7 +49,7 @@ class ActionTest extends TestCase { */ public function testSetLabel($label) { $this->assertSame('', $this->action->getLabel()); - $this->action->setLabel($label); + $this->assertSame($this->action, $this->action->setLabel($label)); $this->assertSame($label, $this->action->getLabel()); } @@ -68,7 +68,7 @@ class ActionTest extends TestCase { /** * @dataProvider dataSetLabelInvalid - * @param string $label + * @param mixed $label * * @expectedException \InvalidArgumentException */ @@ -90,7 +90,7 @@ class ActionTest extends TestCase { */ public function testSetParsedLabel($label) { $this->assertSame('', $this->action->getParsedLabel()); - $this->action->setParsedLabel($label); + $this->assertSame($this->action, $this->action->setParsedLabel($label)); $this->assertSame($label, $this->action->getParsedLabel()); } @@ -108,7 +108,7 @@ class ActionTest extends TestCase { /** * @dataProvider dataSetParsedLabelInvalid - * @param string $label + * @param mixed $label * * @expectedException \InvalidArgumentException */ @@ -132,7 +132,7 @@ class ActionTest extends TestCase { */ public function testSetLink($link, $type) { $this->assertSame('', $this->action->getLink()); - $this->action->setLink($link, $type); + $this->assertSame($this->action, $this->action->setLink($link, $type)); $this->assertSame($link, $this->action->getLink()); $this->assertSame($type, $this->action->getRequestType()); } @@ -162,8 +162,8 @@ class ActionTest extends TestCase { /** * @dataProvider dataSetLinkInvalid - * @param string $link - * @param string $type + * @param mixed $link + * @param mixed $type * * @expectedException \InvalidArgumentException */ @@ -171,6 +171,44 @@ class ActionTest extends TestCase { $this->action->setLink($link, $type); } + public function dataSetPrimary() { + return [ + [true], + [false], + ]; + } + + /** + * @dataProvider dataSetPrimary + * @param bool $primary + */ + public function testSetPrimary($primary) { + $this->assertSame(false, $this->action->isPrimary()); + $this->assertSame($this->action, $this->action->setPrimary($primary)); + $this->assertSame($primary, $this->action->isPrimary()); + } + + public function dataSetPrimaryInvalid() { + return [ + [0], + [1], + [''], + [str_repeat('a', 257)], + [[]], + [[str_repeat('a', 257)]], + ]; + } + + /** + * @dataProvider dataSetPrimaryInvalid + * @param mixed $primary + * + * @expectedException \InvalidArgumentException + */ + public function testSetPrimaryInvalid($primary) { + $this->action->setPrimary($primary); + } + public function testIsValid() { $this->assertFalse($this->action->isValid()); $this->assertFalse($this->action->isValidParsed()); diff --git a/tests/lib/notification/notificationtest.php b/tests/lib/notification/notificationtest.php index 8be49ebdc17..662dc5a6176 100644 --- a/tests/lib/notification/notificationtest.php +++ b/tests/lib/notification/notificationtest.php @@ -93,7 +93,7 @@ class NotificationTest extends TestCase { */ public function testSetApp($app) { $this->assertSame('', $this->notification->getApp()); - $this->notification->setApp($app); + $this->assertSame($this->notification, $this->notification->setApp($app)); $this->assertSame($app, $this->notification->getApp()); } @@ -121,7 +121,7 @@ class NotificationTest extends TestCase { */ public function testSetUser($user) { $this->assertSame('', $this->notification->getUser()); - $this->notification->setUser($user); + $this->assertSame($this->notification, $this->notification->setUser($user)); $this->assertSame($user, $this->notification->getUser()); } @@ -149,7 +149,7 @@ class NotificationTest extends TestCase { */ public function testSetTimestamp($timestamp) { $this->assertSame(0, $this->notification->getTimestamp()); - $this->notification->setTimestamp($timestamp); + $this->assertSame($this->notification, $this->notification->setTimestamp($timestamp)); $this->assertSame($timestamp, $this->notification->getTimestamp()); } @@ -182,7 +182,7 @@ class NotificationTest extends TestCase { public function testSetObject($type, $id) { $this->assertSame('', $this->notification->getObjectType()); $this->assertSame(0, $this->notification->getObjectId()); - $this->notification->setObject($type, $id); + $this->assertSame($this->notification, $this->notification->setObject($type, $id)); $this->assertSame($type, $this->notification->getObjectType()); $this->assertSame($id, $this->notification->getObjectId()); } @@ -233,7 +233,7 @@ class NotificationTest extends TestCase { public function testSetSubject($subject, $parameters) { $this->assertSame('', $this->notification->getSubject()); $this->assertSame([], $this->notification->getSubjectParameters()); - $this->notification->setSubject($subject, $parameters); + $this->assertSame($this->notification, $this->notification->setSubject($subject, $parameters)); $this->assertSame($subject, $this->notification->getSubject()); $this->assertSame($parameters, $this->notification->getSubjectParameters()); } @@ -262,7 +262,7 @@ class NotificationTest extends TestCase { */ public function testSetParsedSubject($subject) { $this->assertSame('', $this->notification->getParsedSubject()); - $this->notification->setParsedSubject($subject); + $this->assertSame($this->notification, $this->notification->setParsedSubject($subject)); $this->assertSame($subject, $this->notification->getParsedSubject()); } @@ -296,7 +296,7 @@ class NotificationTest extends TestCase { public function testSetMessage($message, $parameters) { $this->assertSame('', $this->notification->getMessage()); $this->assertSame([], $this->notification->getMessageParameters()); - $this->notification->setMessage($message, $parameters); + $this->assertSame($this->notification, $this->notification->setMessage($message, $parameters)); $this->assertSame($message, $this->notification->getMessage()); $this->assertSame($parameters, $this->notification->getMessageParameters()); } @@ -325,7 +325,7 @@ class NotificationTest extends TestCase { */ public function testSetParsedMessage($message) { $this->assertSame('', $this->notification->getParsedMessage()); - $this->notification->setParsedMessage($message); + $this->assertSame($this->notification, $this->notification->setParsedMessage($message)); $this->assertSame($message, $this->notification->getParsedMessage()); } @@ -353,7 +353,7 @@ class NotificationTest extends TestCase { */ public function testSetLink($link) { $this->assertSame('', $this->notification->getLink()); - $this->notification->setLink($link); + $this->assertSame($this->notification, $this->notification->setLink($link)); $this->assertSame($link, $this->notification->getLink()); } @@ -387,7 +387,7 @@ class NotificationTest extends TestCase { $action->expects($this->never()) ->method('isValidParsed'); - $this->notification->addAction($action); + $this->assertSame($this->notification, $this->notification->addAction($action)); $this->assertEquals([$action], $this->notification->getActions()); $this->assertEquals([], $this->notification->getParsedActions()); @@ -422,7 +422,7 @@ class NotificationTest extends TestCase { ->method('isPrimary') ->willReturn(true); - $this->notification->addAction($action); + $this->assertSame($this->notification, $this->notification->addAction($action)); $this->setExpectedException('\InvalidArgumentException'); $this->notification->addAction($action); @@ -439,7 +439,7 @@ class NotificationTest extends TestCase { $action->expects($this->never()) ->method('isValid'); - $this->notification->addParsedAction($action); + $this->assertSame($this->notification, $this->notification->addParsedAction($action)); $this->assertEquals([$action], $this->notification->getParsedActions()); $this->assertEquals([], $this->notification->getActions()); @@ -474,7 +474,7 @@ class NotificationTest extends TestCase { ->method('isPrimary') ->willReturn(true); - $this->notification->addParsedAction($action); + $this->assertSame($this->notification, $this->notification->addParsedAction($action)); $this->setExpectedException('\InvalidArgumentException'); $this->notification->addParsedAction($action); -- GitLab From e2cfcd992cf6f4bb5f1cdb9070d3d0ea2a1504e2 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 13 Nov 2015 14:13:16 +0100 Subject: [PATCH 056/344] Allow storage wrappers to through a forbidden exception with retry information --- apps/dav/lib/connector/sabre/directory.php | 8 +++ .../connector/sabre/exception/forbidden.php | 64 +++++++++++++++++++ apps/dav/lib/connector/sabre/file.php | 12 ++++ apps/dav/lib/connector/sabre/objecttree.php | 6 ++ .../tests/unit/connector/sabre/directory.php | 21 ++++++ .../sabre/exception/forbiddentest.php | 44 +++++++++++++ .../sabre/exception/invalidpathtest.php | 10 +-- apps/dav/tests/unit/connector/sabre/file.php | 46 +++++++++++++ lib/private/cache/file.php | 2 + lib/private/files.php | 5 ++ lib/private/files/cache/scanner.php | 2 + lib/public/files/forbiddenexception.php | 55 ++++++++++++++++ 12 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 apps/dav/lib/connector/sabre/exception/forbidden.php create mode 100644 apps/dav/tests/unit/connector/sabre/exception/forbiddentest.php create mode 100644 lib/public/files/forbiddenexception.php diff --git a/apps/dav/lib/connector/sabre/directory.php b/apps/dav/lib/connector/sabre/directory.php index 8c736ea0108..b602dd2f7b1 100644 --- a/apps/dav/lib/connector/sabre/directory.php +++ b/apps/dav/lib/connector/sabre/directory.php @@ -28,8 +28,10 @@ */ namespace OCA\DAV\Connector\Sabre; +use OCA\DAV\Connector\Sabre\Exception\Forbidden; use OCA\DAV\Connector\Sabre\Exception\InvalidPath; use OCA\DAV\Connector\Sabre\Exception\FileLocked; +use OCP\Files\ForbiddenException; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; use Sabre\DAV\Exception\Locked; @@ -117,6 +119,8 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } catch (\OCP\Files\InvalidPathException $ex) { throw new InvalidPath($ex->getMessage()); + } catch (ForbiddenException $ex) { + throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } @@ -146,6 +150,8 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } catch (\OCP\Files\InvalidPathException $ex) { throw new InvalidPath($ex->getMessage()); + } catch (ForbiddenException $ex) { + throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } @@ -247,6 +253,8 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node // assume it wasn't possible to remove due to permission issue throw new \Sabre\DAV\Exception\Forbidden(); } + } catch (ForbiddenException $ex) { + throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } diff --git a/apps/dav/lib/connector/sabre/exception/forbidden.php b/apps/dav/lib/connector/sabre/exception/forbidden.php new file mode 100644 index 00000000000..673958349f3 --- /dev/null +++ b/apps/dav/lib/connector/sabre/exception/forbidden.php @@ -0,0 +1,64 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\DAV\Connector\Sabre\Exception; + +class Forbidden extends \Sabre\DAV\Exception\Forbidden { + + const NS_OWNCLOUD = 'http://owncloud.org/ns'; + + /** + * @var bool + */ + private $retry; + + /** + * @param string $message + * @param bool $retry + * @param \Exception $previous + */ + public function __construct($message, $retry = false, \Exception $previous = null) { + parent::__construct($message, 0, $previous); + $this->retry = $retry; + } + + /** + * This method allows the exception to include additional information + * into the WebDAV error response + * + * @param \Sabre\DAV\Server $server + * @param \DOMElement $errorNode + * @return void + */ + public function serialize(\Sabre\DAV\Server $server,\DOMElement $errorNode) { + + // set ownCloud namespace + $errorNode->setAttribute('xmlns:o', self::NS_OWNCLOUD); + + // adding the retry node + $error = $errorNode->ownerDocument->createElementNS('o:','o:retry', var_export($this->retry, true)); + $errorNode->appendChild($error); + + // adding the message node + $error = $errorNode->ownerDocument->createElementNS('o:','o:reason', $this->getMessage()); + $errorNode->appendChild($error); + } +} diff --git a/apps/dav/lib/connector/sabre/file.php b/apps/dav/lib/connector/sabre/file.php index 961532daf50..a0c35fb2baf 100644 --- a/apps/dav/lib/connector/sabre/file.php +++ b/apps/dav/lib/connector/sabre/file.php @@ -35,9 +35,11 @@ namespace OCA\DAV\Connector\Sabre; use OC\Files\Filesystem; use OCA\DAV\Connector\Sabre\Exception\EntityTooLarge; use OCA\DAV\Connector\Sabre\Exception\FileLocked; +use OCA\DAV\Connector\Sabre\Exception\Forbidden as DAVForbiddenException; use OCA\DAV\Connector\Sabre\Exception\UnsupportedMediaType; use OCP\Encryption\Exceptions\GenericEncryptionException; use OCP\Files\EntityTooLargeException; +use OCP\Files\ForbiddenException; use OCP\Files\InvalidContentException; use OCP\Files\InvalidPathException; use OCP\Files\LockNotAcquiredException; @@ -175,6 +177,8 @@ class File extends Node implements IFile { \OCP\Util::writeLog('webdav', 'renaming part file to final file failed', \OCP\Util::ERROR); throw new Exception('Could not rename part file to final file'); } + } catch (ForbiddenException $ex) { + throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry()); } catch (\Exception $e) { $partStorage->unlink($internalPartPath); $this->convertToSabreException($e); @@ -273,6 +277,8 @@ class File extends Node implements IFile { throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage()); } catch (StorageNotAvailableException $e) { throw new ServiceUnavailable("Failed to open file: " . $e->getMessage()); + } catch (ForbiddenException $ex) { + throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } @@ -296,6 +302,8 @@ class File extends Node implements IFile { } } catch (StorageNotAvailableException $e) { throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage()); + } catch (ForbiddenException $ex) { + throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } @@ -474,6 +482,10 @@ class File extends Node implements IFile { // a more general case - due to whatever reason the content could not be written throw new Forbidden($e->getMessage(), 0, $e); } + if ($e instanceof ForbiddenException) { + // the path for the file was forbidden + throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e); + } if ($e instanceof EntityTooLargeException) { // the file is too big to be stored throw new EntityTooLarge($e->getMessage(), 0, $e); diff --git a/apps/dav/lib/connector/sabre/objecttree.php b/apps/dav/lib/connector/sabre/objecttree.php index 80c0ef74610..2e9c1b9916c 100644 --- a/apps/dav/lib/connector/sabre/objecttree.php +++ b/apps/dav/lib/connector/sabre/objecttree.php @@ -25,10 +25,12 @@ namespace OCA\DAV\Connector\Sabre; +use OCA\DAV\Connector\Sabre\Exception\Forbidden; use OCA\DAV\Connector\Sabre\Exception\InvalidPath; use OCA\DAV\Connector\Sabre\Exception\FileLocked; use OC\Files\FileInfo; use OC\Files\Mount\MoveableMount; +use OCP\Files\ForbiddenException; use OCP\Files\StorageInvalidException; use OCP\Files\StorageNotAvailableException; use OCP\Lock\LockedException; @@ -235,6 +237,8 @@ class ObjectTree extends \Sabre\DAV\Tree { } } catch (StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); + } catch (ForbiddenException $ex) { + throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } @@ -274,6 +278,8 @@ class ObjectTree extends \Sabre\DAV\Tree { $this->fileView->copy($source, $destination); } catch (StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); + } catch (ForbiddenException $ex) { + throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } diff --git a/apps/dav/tests/unit/connector/sabre/directory.php b/apps/dav/tests/unit/connector/sabre/directory.php index 148a91d26db..75c4828641b 100644 --- a/apps/dav/tests/unit/connector/sabre/directory.php +++ b/apps/dav/tests/unit/connector/sabre/directory.php @@ -9,6 +9,8 @@ namespace OCA\DAV\Tests\Unit\Connector\Sabre; +use OCP\Files\ForbiddenException; + class Directory extends \Test\TestCase { /** @var \OC\Files\View | \PHPUnit_Framework_MockObject_MockObject */ @@ -48,6 +50,25 @@ class Directory extends \Test\TestCase { $dir->delete(); } + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\Forbidden + */ + public function testDeleteForbidden() { + // deletion allowed + $this->info->expects($this->once()) + ->method('isDeletable') + ->will($this->returnValue(true)); + + // but fails + $this->view->expects($this->once()) + ->method('rmdir') + ->with('sub') + ->willThrowException(new ForbiddenException('', true)); + + $dir = $this->getDir('sub'); + $dir->delete(); + } + /** * */ diff --git a/apps/dav/tests/unit/connector/sabre/exception/forbiddentest.php b/apps/dav/tests/unit/connector/sabre/exception/forbiddentest.php new file mode 100644 index 00000000000..19799c71b9e --- /dev/null +++ b/apps/dav/tests/unit/connector/sabre/exception/forbiddentest.php @@ -0,0 +1,44 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\Connector\Sabre\Exception; + +use OCA\DAV\Connector\Sabre\Exception\Forbidden; + +class ForbiddenTest extends \Test\TestCase { + + public function testSerialization() { + + // create xml doc + $DOM = new \DOMDocument('1.0','utf-8'); + $DOM->formatOutput = true; + $error = $DOM->createElementNS('DAV:','d:error'); + $error->setAttribute('xmlns:s', \Sabre\DAV\Server::NS_SABREDAV); + $DOM->appendChild($error); + + // serialize the exception + $message = "1234567890"; + $retry = false; + $expectedXml = << + + false + 1234567890 + + +EOD; + + $ex = new Forbidden($message, $retry); + $server = $this->getMock('Sabre\DAV\Server'); + $ex->serialize($server, $error); + + // assert + $xml = $DOM->saveXML(); + $this->assertEquals($expectedXml, $xml); + } +} diff --git a/apps/dav/tests/unit/connector/sabre/exception/invalidpathtest.php b/apps/dav/tests/unit/connector/sabre/exception/invalidpathtest.php index 19e82320d55..4296a4d5618 100644 --- a/apps/dav/tests/unit/connector/sabre/exception/invalidpathtest.php +++ b/apps/dav/tests/unit/connector/sabre/exception/invalidpathtest.php @@ -1,15 +1,15 @@ * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ + +namespace OCA\DAV\Tests\Unit\Connector\Sabre\Exception; + +use OCA\DAV\Connector\Sabre\Exception\InvalidPath; + class InvalidPathTest extends \Test\TestCase { public function testSerialization() { diff --git a/apps/dav/tests/unit/connector/sabre/file.php b/apps/dav/tests/unit/connector/sabre/file.php index 94dadf88fe4..399634f8bee 100644 --- a/apps/dav/tests/unit/connector/sabre/file.php +++ b/apps/dav/tests/unit/connector/sabre/file.php @@ -9,6 +9,7 @@ namespace OCA\DAV\Tests\Unit\Connector\Sabre; use OC\Files\Storage\Local; +use OCP\Files\ForbiddenException; use Test\HookHelper; use OC\Files\Filesystem; use OCP\Lock\ILockingProvider; @@ -72,6 +73,10 @@ class File extends \Test\TestCase { new \OCP\Files\InvalidPathException(), 'Sabre\DAV\Exception\Forbidden' ], + [ + new \OCP\Files\ForbiddenException('', true), + 'OCA\DAV\Connector\Sabre\Exception\Forbidden' + ], [ new \OCP\Files\LockNotAcquiredException('/test.txt', 1), 'OCA\DAV\Connector\Sabre\Exception\FileLocked' @@ -690,6 +695,29 @@ class File extends \Test\TestCase { $file->delete(); } + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\Forbidden + */ + public function testDeleteThrowsWhenDeletionThrows() { + // setup + $view = $this->getMock('\OC\Files\View', + array()); + + // but fails + $view->expects($this->once()) + ->method('unlink') + ->willThrowException(new ForbiddenException('', true)); + + $info = new \OC\Files\FileInfo('/test.txt', null, null, array( + 'permissions' => \OCP\Constants::PERMISSION_ALL + ), null); + + $file = new \OCA\DAV\Connector\Sabre\File($view, $info); + + // action + $file->delete(); + } + /** * Asserts hook call * @@ -835,4 +863,22 @@ class File extends \Test\TestCase { $file->get(); } + + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\Forbidden + */ + public function testGetFopenThrows() { + $view = $this->getMock('\OC\Files\View', ['fopen'], array()); + $view->expects($this->atLeastOnce()) + ->method('fopen') + ->willThrowException(new ForbiddenException('', true)); + + $info = new \OC\Files\FileInfo('/test.txt', null, null, array( + 'permissions' => \OCP\Constants::PERMISSION_ALL + ), null); + + $file = new \OCA\DAV\Connector\Sabre\File($view, $info); + + $file->get(); + } } diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php index 1cda05f28e5..31d4718d18a 100644 --- a/lib/private/cache/file.php +++ b/lib/private/cache/file.php @@ -185,6 +185,8 @@ class File implements ICache { } catch (\OCP\Lock\LockedException $e) { // ignore locked chunks \OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', array('app' => 'core')); + } catch (\OCP\Files\ForbiddenException $e) { + \OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', array('app' => 'core')); } catch (\OCP\Files\LockNotAcquiredException $e) { \OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', array('app' => 'core')); } diff --git a/lib/private/files.php b/lib/private/files.php index 9be5fc9a12f..af10f3e1e32 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -142,6 +142,11 @@ class OC_Files { $l = \OC::$server->getL10N('core'); $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint); + } catch (\OCP\Files\ForbiddenException $ex) { + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); + OC::$server->getLogger()->logException($ex); + $l = \OC::$server->getL10N('core'); + \OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage()); } catch (\Exception $ex) { self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); OC::$server->getLogger()->logException($ex); diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php index 35043029dc3..983e12d7639 100644 --- a/lib/private/files/cache/scanner.php +++ b/lib/private/files/cache/scanner.php @@ -432,6 +432,8 @@ class Scanner extends BasicEmitter { // skip unavailable storages } catch (\OCP\Files\StorageNotAvailableException $e) { // skip unavailable storages + } catch (\OCP\Files\ForbiddenException $e) { + // skip forbidden storages } catch (\OCP\Lock\LockedException $e) { // skip unavailable storages } diff --git a/lib/public/files/forbiddenexception.php b/lib/public/files/forbiddenexception.php new file mode 100644 index 00000000000..13490c6eae3 --- /dev/null +++ b/lib/public/files/forbiddenexception.php @@ -0,0 +1,55 @@ + + * + * @copyright Copyright (c) 2015, 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 + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Files; + +/** + * Class ForbiddenException + * + * @package OCP\Files + * @since 9.0.0 + */ +class ForbiddenException extends \Exception { + + /** @var bool */ + private $retry; + + /** + * @param string $message + * @param bool $retry + * @param \Exception $previous previous exception for cascading + * @since 9.0.0 + */ + public function __construct($message, $retry, \Exception $previous = null) { + parent::__construct($message, 0, $previous); + $this->retry = $retry; + } + + /** + * @return bool + * @since 9.0.0 + */ + public function getRetry() { + return (bool) $this->retry; + } +} -- GitLab From cbd94ce355b18e591e2cb59a18db02c04e0b14c6 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 17 Nov 2015 14:09:29 +0100 Subject: [PATCH 057/344] Unset `path` for shared with me The original path is not required for a share recipient. --- apps/files_sharing/api/local.php | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/files_sharing/api/local.php b/apps/files_sharing/api/local.php index bb5136a0c99..aaafafb269f 100644 --- a/apps/files_sharing/api/local.php +++ b/apps/files_sharing/api/local.php @@ -233,6 +233,7 @@ class Local { if (\OC::$server->getPreviewManager()->isMimeSupported($share['mimetype'])) { $share['isPreviewAvailable'] = true; } + unset($share['path']); } } $result = new \OC_OCS_Result($shares); -- GitLab From cd4380c32230c583cfe7d4ff3e630d272d4c9a1a Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Wed, 18 Nov 2015 01:55:08 -0500 Subject: [PATCH 058/344] [tx-robot] updated from transifex --- apps/files/l10n/nl.js | 2 ++ apps/files/l10n/nl.json | 2 ++ apps/user_ldap/l10n/tr.js | 1 + apps/user_ldap/l10n/tr.json | 1 + core/l10n/nl.js | 1 + core/l10n/nl.json | 1 + 6 files changed, 8 insertions(+) diff --git a/apps/files/l10n/nl.js b/apps/files/l10n/nl.js index d60598ca147..88eb77c02a5 100644 --- a/apps/files/l10n/nl.js +++ b/apps/files/l10n/nl.js @@ -105,6 +105,8 @@ OC.L10N.register( "Maximum upload size" : "Maximale bestandsgrootte voor uploads", "max. possible: " : "max. mogelijk: ", "Save" : "Bewaren", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Met PHP-FPM kan het 5 minuten duren voordat wijzigingen zijn doorgevoerd.", + "Missing permissions to edit from here." : "Ontbrekende rechten om vanaf hier te bewerken.", "Settings" : "Instellingen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Gebruik deze link om uw bestanden via WebDAV te benaderen", diff --git a/apps/files/l10n/nl.json b/apps/files/l10n/nl.json index 28f80c09af7..0eca44aaa0d 100644 --- a/apps/files/l10n/nl.json +++ b/apps/files/l10n/nl.json @@ -103,6 +103,8 @@ "Maximum upload size" : "Maximale bestandsgrootte voor uploads", "max. possible: " : "max. mogelijk: ", "Save" : "Bewaren", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Met PHP-FPM kan het 5 minuten duren voordat wijzigingen zijn doorgevoerd.", + "Missing permissions to edit from here." : "Ontbrekende rechten om vanaf hier te bewerken.", "Settings" : "Instellingen", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Gebruik deze link om uw bestanden via WebDAV te benaderen", diff --git a/apps/user_ldap/l10n/tr.js b/apps/user_ldap/l10n/tr.js index cbe95a194c5..c9798c5382d 100644 --- a/apps/user_ldap/l10n/tr.js +++ b/apps/user_ldap/l10n/tr.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "Base DN tespit edilemedi, lütfen elle girin.", "{nthServer}. Server" : "{nthServer}. Sunucu", "No object found in the given Base DN. Please revise." : "Girilen Base DN içerisinde nesne bulunamadı. Lütfen gözden geçirin.", + "More than 1,000 directory entries available." : "1000'den fazla dizin şuan müsait durumdadır.", " entries available within the provided Base DN" : " girdi sağlanan Base DN içerisinde mevcut", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Bir hata oluştu. Lütfen Base DN ile birlikte bağlantı ayarlarını ve kimlik bilgilerini denetleyin.", "Do you really want to delete the current Server Configuration?" : "Şu anki sunucu yapılandırmasını silmek istediğinizden emin misiniz?", diff --git a/apps/user_ldap/l10n/tr.json b/apps/user_ldap/l10n/tr.json index 2bd0bd59907..c60842078a7 100644 --- a/apps/user_ldap/l10n/tr.json +++ b/apps/user_ldap/l10n/tr.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "Base DN tespit edilemedi, lütfen elle girin.", "{nthServer}. Server" : "{nthServer}. Sunucu", "No object found in the given Base DN. Please revise." : "Girilen Base DN içerisinde nesne bulunamadı. Lütfen gözden geçirin.", + "More than 1,000 directory entries available." : "1000'den fazla dizin şuan müsait durumdadır.", " entries available within the provided Base DN" : " girdi sağlanan Base DN içerisinde mevcut", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Bir hata oluştu. Lütfen Base DN ile birlikte bağlantı ayarlarını ve kimlik bilgilerini denetleyin.", "Do you really want to delete the current Server Configuration?" : "Şu anki sunucu yapılandırmasını silmek istediğinizden emin misiniz?", diff --git a/core/l10n/nl.js b/core/l10n/nl.js index f4702077004..fe5f45c95ea 100644 --- a/core/l10n/nl.js +++ b/core/l10n/nl.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Neem contact op met uw systeembeheerder als deze melding aanhoudt of onverwacht verscheen.", "Thank you for your patience." : "Bedankt voor uw geduld.", "You are accessing the server from an untrusted domain." : "U benadert de server vanaf een niet vertrouwd domein.", + "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." : "Neem contact op met uw beheerder. Als u de beheerder van deze service bent, configureer dan de \"trusted_domains\" instelling in config/config.php. Een voorbeeldconfiguratie is gegeven in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Afhankelijk van uw configuratie zou u als beheerder ook de onderstaande knop kunnen gebruiken om dit domein te vertrouwen.", "Add \"%s\" as trusted domain" : "\"%s\" toevoegen als vertrouwd domein", "App update required" : "Bijwerken App vereist", diff --git a/core/l10n/nl.json b/core/l10n/nl.json index a86bbe3d4af..117070e8399 100644 --- a/core/l10n/nl.json +++ b/core/l10n/nl.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Neem contact op met uw systeembeheerder als deze melding aanhoudt of onverwacht verscheen.", "Thank you for your patience." : "Bedankt voor uw geduld.", "You are accessing the server from an untrusted domain." : "U benadert de server vanaf een niet vertrouwd domein.", + "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." : "Neem contact op met uw beheerder. Als u de beheerder van deze service bent, configureer dan de \"trusted_domains\" instelling in config/config.php. Een voorbeeldconfiguratie is gegeven in config/config.sample.php.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Afhankelijk van uw configuratie zou u als beheerder ook de onderstaande knop kunnen gebruiken om dit domein te vertrouwen.", "Add \"%s\" as trusted domain" : "\"%s\" toevoegen als vertrouwd domein", "App update required" : "Bijwerken App vereist", -- GitLab From 978303e03e7e0728c3d2a3555b59b8c6e329b1a6 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 18 Nov 2015 11:41:04 +0100 Subject: [PATCH 059/344] Add internal fileid to webdav response Introduce a new property "oc:fileid" to return the internal file id. This is because the original "oc:id" property is a compound and it is not possible to extract the real id without knowing the instance id. The instance id is not available to external clients. --- apps/dav/lib/connector/sabre/filesplugin.php | 6 ++++++ apps/dav/lib/connector/sabre/node.php | 7 +++++++ apps/dav/tests/unit/connector/sabre/filesplugin.php | 12 +++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/dav/lib/connector/sabre/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php index 00d5d2cd725..d68397dcaa3 100644 --- a/apps/dav/lib/connector/sabre/filesplugin.php +++ b/apps/dav/lib/connector/sabre/filesplugin.php @@ -37,6 +37,7 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { // namespace const NS_OWNCLOUD = 'http://owncloud.org/ns'; const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id'; + const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid'; const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions'; const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL'; const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size'; @@ -98,6 +99,7 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { $server->xmlNamespaces[self::NS_OWNCLOUD] = 'oc'; $server->protectedProperties[] = self::FILEID_PROPERTYNAME; + $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME; $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME; $server->protectedProperties[] = self::SIZE_PROPERTYNAME; $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME; @@ -175,6 +177,10 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { return $node->getFileId(); }); + $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) { + return $node->getInternalFileId(); + }); + $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) { $perms = $node->getDavPermissions(); if ($this->isPublic) { diff --git a/apps/dav/lib/connector/sabre/node.php b/apps/dav/lib/connector/sabre/node.php index ae7dd51fc94..daf82ba6f0d 100644 --- a/apps/dav/lib/connector/sabre/node.php +++ b/apps/dav/lib/connector/sabre/node.php @@ -206,6 +206,13 @@ abstract class Node implements \Sabre\DAV\INode { return null; } + /** + * @return string + */ + public function getInternalFileId() { + return $this->info->getId(); + } + /** * @return string|null */ diff --git a/apps/dav/tests/unit/connector/sabre/filesplugin.php b/apps/dav/tests/unit/connector/sabre/filesplugin.php index 55c8dd49e17..2e3338fefa1 100644 --- a/apps/dav/tests/unit/connector/sabre/filesplugin.php +++ b/apps/dav/tests/unit/connector/sabre/filesplugin.php @@ -11,6 +11,7 @@ namespace OCA\DAV\Tests\Unit\Connector\Sabre; class FilesPlugin extends \Test\TestCase { const GETETAG_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::GETETAG_PROPERTYNAME; const FILEID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::FILEID_PROPERTYNAME; + const INTERNAL_FILEID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::INTERNAL_FILEID_PROPERTYNAME; const SIZE_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::SIZE_PROPERTYNAME; const PERMISSIONS_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::PERMISSIONS_PROPERTYNAME; const LASTMODIFIED_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::LASTMODIFIED_PROPERTYNAME; @@ -69,7 +70,10 @@ class FilesPlugin extends \Test\TestCase { $node->expects($this->any()) ->method('getFileId') - ->will($this->returnValue(123)); + ->will($this->returnValue('00000123instanceid')); + $node->expects($this->any()) + ->method('getInternalFileId') + ->will($this->returnValue('123')); $node->expects($this->any()) ->method('getEtag') ->will($this->returnValue('"abc"')); @@ -90,6 +94,7 @@ class FilesPlugin extends \Test\TestCase { array( self::GETETAG_PROPERTYNAME, self::FILEID_PROPERTYNAME, + self::INTERNAL_FILEID_PROPERTYNAME, self::SIZE_PROPERTYNAME, self::PERMISSIONS_PROPERTYNAME, self::DOWNLOADURL_PROPERTYNAME, @@ -125,7 +130,8 @@ class FilesPlugin extends \Test\TestCase { ); $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME)); - $this->assertEquals(123, $propFind->get(self::FILEID_PROPERTYNAME)); + $this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME)); + $this->assertEquals('123', $propFind->get(self::INTERNAL_FILEID_PROPERTYNAME)); $this->assertEquals(null, $propFind->get(self::SIZE_PROPERTYNAME)); $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME)); $this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME)); @@ -186,7 +192,7 @@ class FilesPlugin extends \Test\TestCase { ); $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME)); - $this->assertEquals(123, $propFind->get(self::FILEID_PROPERTYNAME)); + $this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME)); $this->assertEquals(1025, $propFind->get(self::SIZE_PROPERTYNAME)); $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME)); $this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME)); -- GitLab From fbcdf170892bcde39b202d021eb9107e9820c26c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 18 Nov 2015 12:53:20 +0100 Subject: [PATCH 060/344] Fix doc blocks --- .../features/bootstrap/FeatureContext.php | 76 ++++++++++--------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 46c86f1300b..561a957f7d3 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -60,6 +60,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * Parses the xml answer to get ocs response which doesn't match with * http one in v1 of the api. + * @param ResponseInterface $response + * @return string */ public function getOCSResponse($response) { return $response->xml()->meta[0]->statuscode; @@ -67,6 +69,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * Parses the xml answer to get the array of users returned. + * @param ResponseInterface $resp + * @return array */ public function getArrayOfUsersResponded($resp) { $listCheckedElements = $resp->xml()->data[0]->users[0]->element; @@ -76,6 +80,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * Parses the xml answer to get the array of groups returned. + * @param ResponseInterface $resp + * @return array */ public function getArrayOfGroupsResponded($resp) { $listCheckedElements = $resp->xml()->data[0]->groups[0]->element; @@ -85,6 +91,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * Parses the xml answer to get the array of subadmins returned. + * @param ResponseInterface $resp + * @return array */ public function getArrayOfSubadminsResponded($resp) { $listCheckedElements = $resp->xml()->data[0]->element; @@ -94,6 +102,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * Parses the xml answer to get the array of apps returned. + * @param ResponseInterface $resp + * @return array */ public function getArrayOfAppsResponded($resp) { $listCheckedElements = $resp->xml()->data[0]->apps[0]->element; @@ -108,10 +118,10 @@ class FeatureContext implements Context, SnippetAcceptingContext { $a = array_map(function($subArray) { return $subArray[0]; }, $arrayOfArrays); return $a; } - + /** * @Then /^users returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData + * @param \Behat\Gherkin\Node\TableNode|null $usersList */ public function theUsersShouldBe($usersList) { if ($usersList instanceof \Behat\Gherkin\Node\TableNode) { @@ -125,7 +135,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * @Then /^groups returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData + * @param \Behat\Gherkin\Node\TableNode|null $groupsList */ public function theGroupsShouldBe($groupsList) { if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { @@ -139,7 +149,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * @Then /^subadmin groups returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData + * @param \Behat\Gherkin\Node\TableNode|null $groupsList */ public function theSubadminGroupsShouldBe($groupsList) { if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { @@ -153,7 +163,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * @Then /^subadmin users returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData + * @param \Behat\Gherkin\Node\TableNode|null $groupsList */ public function theSubadminUsersShouldBe($groupsList) { $this->theSubadminGroupsShouldBe($groupsList); @@ -161,7 +171,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * @Then /^apps returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData + * @param \Behat\Gherkin\Node\TableNode|null $appList */ public function theAppsShouldBe($appList) { if ($appList instanceof \Behat\Gherkin\Node\TableNode) { @@ -206,7 +216,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { */ public function assureUserExists($user) { try { - $this->userExists($user); + $this->userExists($user); } catch (\GuzzleHttp\Exception\ClientException $ex) { $previous_user = $this->currentUser; $this->currentUser = "admin"; @@ -276,7 +286,6 @@ class FeatureContext implements Context, SnippetAcceptingContext { } $this->response = $client->get($fullUrl, $options); - $subadmins = array($user); $respondedArray = $this->getArrayOfSubadminsResponded($this->response); sort($respondedArray); PHPUnit_Framework_Assert::assertContains($user, $respondedArray); @@ -295,7 +304,6 @@ class FeatureContext implements Context, SnippetAcceptingContext { } $this->response = $client->get($fullUrl, $options); - $subadmins = array($user); $respondedArray = $this->getArrayOfSubadminsResponded($this->response); sort($respondedArray); PHPUnit_Framework_Assert::assertNotContains($user, $respondedArray); @@ -498,7 +506,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { */ public function assureGroupExists($group) { try { - $this->groupExists($group); + $this->groupExists($group); } catch (\GuzzleHttp\Exception\ClientException $ex) { $previous_user = $this->currentUser; $this->currentUser = "admin"; @@ -608,8 +616,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { $fileinfo = $finfo->file("./$filename", FILEINFO_MIME_TYPE); PHPUnit_Framework_Assert::assertEquals($fileinfo, "text/plain"); if (file_exists("./$filename")) { - unlink("./$filename"); - } + unlink("./$filename"); + } } /** @@ -624,7 +632,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { else{ $token = $this->lastShareData->data->token; } - + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav"; $options['auth'] = [$token, $password]; $options['save_to'] = "./$filename"; @@ -633,8 +641,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { $fileinfo = $finfo->file("./$filename", FILEINFO_MIME_TYPE); PHPUnit_Framework_Assert::assertEquals($fileinfo, "text/plain"); if (file_exists("./$filename")) { - unlink("./$filename"); - } + unlink("./$filename"); + } } /** @@ -658,7 +666,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * @When /^Updating last share with$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData + * @param \Behat\Gherkin\Node\TableNode|null $body */ public function updatingLastShare($body) { $share_id = $this->lastShareData->data[0]->id; @@ -691,11 +699,11 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function createShare($user, - $path = null, - $shareType = null, - $shareWith = null, - $publicUpload = null, - $password = null, + $path = null, + $shareType = null, + $shareWith = null, + $publicUpload = null, + $password = null, $permissions = null){ $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares"; $client = new Client(); @@ -708,26 +716,26 @@ class FeatureContext implements Context, SnippetAcceptingContext { } $fd = []; if (!is_null($path)){ - $fd['path'] = $path; + $fd['path'] = $path; } if (!is_null($shareType)){ - $fd['shareType'] = $shareType; + $fd['shareType'] = $shareType; } if (!is_null($shareWith)){ - $fd['shareWith'] = $shareWith; + $fd['shareWith'] = $shareWith; } if (!is_null($publicUpload)){ - $fd['publicUpload'] = $publicUpload; + $fd['publicUpload'] = $publicUpload; } if (!is_null($password)){ - $fd['password'] = $password; + $fd['password'] = $password; } if (!is_null($permissions)){ - $fd['permissions'] = $permissions; + $fd['permissions'] = $permissions; } $options['body'] = $fd; - + try { $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); $this->lastShareData = $this->response->xml(); @@ -740,7 +748,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function isExpectedUrl($possibleUrl, $finalPart){ $baseUrlChopped = substr($this->baseUrl, 0, -4); $endCharacter = strlen($baseUrlChopped) + strlen($finalPart); - return (substr($possibleUrl,0,$endCharacter) == "$baseUrlChopped" . "$finalPart"); + return (substr($possibleUrl,0,$endCharacter) == "$baseUrlChopped" . "$finalPart"); } public function isFieldInResponse($field, $contentExpected){ @@ -877,7 +885,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { public static function removeFile($path, $filename){ if (file_exists("$path" . "$filename")) { unlink("$path" . "$filename"); - } + } } /** @@ -888,7 +896,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { file_put_contents("../../core/skeleton/" . "textfile" . "$i" . ".txt", "ownCloud test text file\n"); } if (!file_exists("../../core/skeleton/FOLDER")) { - mkdir("../../core/skeleton/FOLDER", 0777, true); + mkdir("../../core/skeleton/FOLDER", 0777, true); } } @@ -899,9 +907,9 @@ class FeatureContext implements Context, SnippetAcceptingContext { public static function removeFilesFromSkeleton(){ for ($i=0; $i<5; $i++){ self::removeFile("../../core/skeleton/", "textfile" . "$i" . ".txt"); - } - if (!is_dir("../../core/skeleton/FOLDER")) { - rmdir("../../core/skeleton/FOLDER"); + } + if (!is_dir("../../core/skeleton/FOLDER")) { + rmdir("../../core/skeleton/FOLDER"); } } -- GitLab From 90b020cf8862d60c315eb91e62ca9a6e3d938962 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 18 Nov 2015 12:53:36 +0100 Subject: [PATCH 061/344] Delete when it is a directory... --- build/integration/features/bootstrap/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 561a957f7d3..3d579f52810 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -908,7 +908,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { for ($i=0; $i<5; $i++){ self::removeFile("../../core/skeleton/", "textfile" . "$i" . ".txt"); } - if (!is_dir("../../core/skeleton/FOLDER")) { + if (is_dir("../../core/skeleton/FOLDER")) { rmdir("../../core/skeleton/FOLDER"); } } -- GitLab From 9671103121cef93470b5badf7e46ffd8ecbddf2d Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Mon, 16 Nov 2015 14:24:56 +0100 Subject: [PATCH 062/344] clarify log level setting design, fix #20514 --- settings/templates/admin.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 27785c26dfe..24af4964248 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -491,15 +491,6 @@ if ($_['cronErrors']) {

t('Log'));?>

- t('Log level'));?> @@ -537,6 +528,16 @@ if ($_['cronErrors']) { + +

t('What to log'));?>

-- GitLab From 1d82d93baa127e951790003b0634af8841dceb0d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 18 Nov 2015 17:08:02 +0100 Subject: [PATCH 063/344] Implement getOwner for external share storage --- apps/files_sharing/lib/external/storage.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/external/storage.php b/apps/files_sharing/lib/external/storage.php index 270d8b6d1b8..2a0d827e064 100644 --- a/apps/files_sharing/lib/external/storage.php +++ b/apps/files_sharing/lib/external/storage.php @@ -250,7 +250,7 @@ class Storage extends DAV implements ISharedStorage { $response = $client->post($url, ['body' => ['password' => $password]]); } catch (\GuzzleHttp\Exception\RequestException $e) { if ($e->getCode() === 401 || $e->getCode() === 403) { - throw new ForbiddenException(); + throw new ForbiddenException(); } // throw this to be on the safe side: the share will still be visible // in the UI in case the failure is intermittent, and the user will @@ -260,4 +260,9 @@ class Storage extends DAV implements ISharedStorage { return json_decode($response->getBody(), true); } + + public function getOwner($path) { + list(, $remote) = explode('://', $this->remote, 2); + return $this->remoteUser . '@' . $remote; + } } -- GitLab From 71b86c0ed4adc0a774e852338f1cd1fb192b7569 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 18 Nov 2015 17:08:18 +0100 Subject: [PATCH 064/344] Handle non existing users as owner in the view --- lib/private/files/view.php | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 7dd83588ec6..cee4b182425 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -46,11 +46,13 @@ namespace OC\Files; use Icewind\Streams\CallbackWrapper; use OC\Files\Cache\Updater; use OC\Files\Mount\MoveableMount; +use OC\User\User; use OCP\Files\FileNameTooLongException; use OCP\Files\InvalidCharacterInPathException; use OCP\Files\InvalidPathException; use OCP\Files\NotFoundException; use OCP\Files\ReservedWordException; +use OCP\IUser; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; @@ -687,14 +689,14 @@ class View { } else { $result = false; } - // moving a file/folder within the same mount point + // moving a file/folder within the same mount point } elseif ($storage1 == $storage2) { if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); } else { $result = false; } - // moving a file/folder between storages (from $storage1 to $storage2) + // moving a file/folder between storages (from $storage1 to $storage2) } else { $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); } @@ -1163,6 +1165,19 @@ class View { return $this->basicOperation('hasUpdated', $path, array(), $time); } + /** + * @param string $ownerId + * @return \OC\User\User + */ + private function getUserObjectForOwner($ownerId) { + $owner = \OC::$server->getUserManager()->get($ownerId); + if ($owner instanceof IUser) { + return $owner; + } else { + return new User($ownerId, null); + } + } + /** * get the filesystem info * @@ -1250,7 +1265,7 @@ class View { $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE; } - $owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath)); + $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath)); return new FileInfo($path, $storage, $internalPath, $data, $mount, $owner); } @@ -1317,7 +1332,7 @@ class View { if (\OCP\Util::isSharingDisabledForUser()) { $content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; } - $owner = \OC::$server->getUserManager()->get($storage->getOwner($content['path'])); + $owner = $this->getUserObjectForOwner($storage->getOwner($content['path'])); $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner); } @@ -1387,7 +1402,7 @@ class View { $rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; } - $owner = \OC::$server->getUserManager()->get($subStorage->getOwner('')); + $owner = $this->getUserObjectForOwner($subStorage->getOwner('')); $files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner); } } -- GitLab From d831c255ea726b8e8aaa0b3c1a8186808b82f73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 18 Nov 2015 17:37:07 +0100 Subject: [PATCH 065/344] Update .well-known redirects to the new dav endpoint --- .htaccess | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.htaccess b/.htaccess index 918fcbd18e8..615f5e7fc96 100644 --- a/.htaccess +++ b/.htaccess @@ -38,8 +38,8 @@ RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L] RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L] - RewriteRule ^\.well-known/carddav /remote.php/carddav/ [R=301,L] - RewriteRule ^\.well-known/caldav /remote.php/caldav/ [R=301,L] + RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L] + RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L] RewriteRule ^remote/(.*) remote.php [QSA,L] RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] -- GitLab From 68321efd29184fbc1bef409ec41f9b38501116ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 18 Nov 2015 17:38:46 +0100 Subject: [PATCH 066/344] Revert "Update .well-known redirects to the new dav endpoint" This reverts commit d831c255ea726b8e8aaa0b3c1a8186808b82f73e. --- .htaccess | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.htaccess b/.htaccess index 615f5e7fc96..918fcbd18e8 100644 --- a/.htaccess +++ b/.htaccess @@ -38,8 +38,8 @@ RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L] RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L] - RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L] - RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L] + RewriteRule ^\.well-known/carddav /remote.php/carddav/ [R=301,L] + RewriteRule ^\.well-known/caldav /remote.php/caldav/ [R=301,L] RewriteRule ^remote/(.*) remote.php [QSA,L] RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] -- GitLab From 7451e5bebc9455764a3731df0bf3dc09e20f0d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 18 Nov 2015 17:40:27 +0100 Subject: [PATCH 067/344] Update .well-known redirects to the new dav endpoint This reverts commit 68321efd29184fbc1bef409ec41f9b38501116ef. --- .htaccess | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.htaccess b/.htaccess index 918fcbd18e8..615f5e7fc96 100644 --- a/.htaccess +++ b/.htaccess @@ -38,8 +38,8 @@ RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L] RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L] - RewriteRule ^\.well-known/carddav /remote.php/carddav/ [R=301,L] - RewriteRule ^\.well-known/caldav /remote.php/caldav/ [R=301,L] + RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L] + RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L] RewriteRule ^remote/(.*) remote.php [QSA,L] RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] -- GitLab From 048ad25416f3ca697d48af320b6b2a97352f0670 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Wed, 18 Nov 2015 22:28:48 +0100 Subject: [PATCH 068/344] Use proper variable `$shares` is not defined. Introduced with https://github.com/owncloud/core/commit/c3e7d324c5e61eb087fb2ea5102d332f9f08db3d and thus also in stable8.2 --- apps/files_sharing/api/remote.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_sharing/api/remote.php b/apps/files_sharing/api/remote.php index 41ebb6e2eab..fb692f8a9a6 100644 --- a/apps/files_sharing/api/remote.php +++ b/apps/files_sharing/api/remote.php @@ -98,7 +98,7 @@ class Remote { */ private static function extendShareInfo($share) { $view = new \OC\Files\View('/' . \OC_User::getUser() . '/files/'); - $info = $view->getFileInfo($shares['mountpoint']); + $info = $view->getFileInfo($share['mountpoint']); $share['mimetype'] = $info->getMimetype(); $share['mtime'] = $info->getMtime(); -- GitLab From 5d2e1268cd72d2a2a44136a298a675f8fe72d93d Mon Sep 17 00:00:00 2001 From: blizzz Date: Wed, 18 Nov 2015 22:48:35 +0100 Subject: [PATCH 069/344] Avoid double slashes in URL when trying to add an remote share When being on a link share and clicking "Add to your ownCloud" a double slash might be inserted in the URL if the entered ownCloud host ended with a slash. Results in a server error. --- apps/files_sharing/js/public.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 246b639f652..b3098f9dcdc 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -274,8 +274,12 @@ OCA.Sharing.PublicApp = { _saveToOwnCloud: function (remote, token, owner, name, isProtected) { var location = window.location.protocol + '//' + window.location.host + OC.webroot; + + if(remote.substr(-1) !== '/') { + remote += '/' + }; - var url = remote + '/index.php/apps/files#' + 'remote=' + encodeURIComponent(location) // our location is the remote for the other server + var url = remote + 'index.php/apps/files#' + 'remote=' + encodeURIComponent(location) // our location is the remote for the other server + "&token=" + encodeURIComponent(token) + "&owner=" + encodeURIComponent(owner) + "&name=" + encodeURIComponent(name) + "&protected=" + isProtected; -- GitLab From c10be07c1b8538361dbfca1ae12bb279b72fe377 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Thu, 19 Nov 2015 01:55:13 -0500 Subject: [PATCH 070/344] [tx-robot] updated from transifex --- apps/files/l10n/hu_HU.js | 2 ++ apps/files/l10n/hu_HU.json | 2 ++ core/l10n/hu_HU.js | 1 + core/l10n/hu_HU.json | 1 + lib/l10n/fr.js | 2 +- lib/l10n/fr.json | 2 +- lib/l10n/hu_HU.js | 12 ++++++++++++ lib/l10n/hu_HU.json | 12 ++++++++++++ settings/l10n/zh_TW.js | 2 +- settings/l10n/zh_TW.json | 2 +- 10 files changed, 34 insertions(+), 4 deletions(-) diff --git a/apps/files/l10n/hu_HU.js b/apps/files/l10n/hu_HU.js index 48e9bfb168b..3c12e4bd486 100644 --- a/apps/files/l10n/hu_HU.js +++ b/apps/files/l10n/hu_HU.js @@ -106,6 +106,8 @@ OC.L10N.register( "Maximum upload size" : "Maximális feltölthető fájlméret", "max. possible: " : "max. lehetséges: ", "Save" : "Mentés", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "PHP-FPM-mel akár 5 percbe is telhet, míg ez a beállítás érvénybe lép.", + "Missing permissions to edit from here." : "Innen nem lehet szerkeszteni hiányzó jogosultság miatt.", "Settings" : "Beállítások", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Ezt a címet használja, ha WebDAV-on keresztül szeretné elérni a fájljait", diff --git a/apps/files/l10n/hu_HU.json b/apps/files/l10n/hu_HU.json index c72dfa0d48b..b1bde8b7d51 100644 --- a/apps/files/l10n/hu_HU.json +++ b/apps/files/l10n/hu_HU.json @@ -104,6 +104,8 @@ "Maximum upload size" : "Maximális feltölthető fájlméret", "max. possible: " : "max. lehetséges: ", "Save" : "Mentés", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "PHP-FPM-mel akár 5 percbe is telhet, míg ez a beállítás érvénybe lép.", + "Missing permissions to edit from here." : "Innen nem lehet szerkeszteni hiányzó jogosultság miatt.", "Settings" : "Beállítások", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Ezt a címet használja, ha WebDAV-on keresztül szeretné elérni a fájljait", diff --git a/core/l10n/hu_HU.js b/core/l10n/hu_HU.js index 0feea423eb6..3d0276c1700 100644 --- a/core/l10n/hu_HU.js +++ b/core/l10n/hu_HU.js @@ -269,6 +269,7 @@ OC.L10N.register( "Contact your system administrator if this message persists or appeared unexpectedly." : "Ha ez az üzenet ismételten vagy indokolatlanul megjelenik, akkor keresse a rendszergazda segítségét!", "Thank you for your patience." : "Köszönjük a türelmét.", "You are accessing the server from an untrusted domain." : "A kiszolgálót nem megbízható tartományból éri el.", + "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." : "Kérjük keresse fel a rendszergazdát! Ha ennek a telepítésnek Ön a rendszergazdája, akkor állítsa be a config/config.php állományban a \"trusted_domain\" paramétert! A config/config.sample.php állományban talál példát a beállításra.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "A beállításoktól függően, rendszergazdaként lehetséges, hogy az alábbi gombot is használhatja a tartomány megbízhatóvá tételéhez.", "Add \"%s\" as trusted domain" : "Adjuk hozzá \"%s\"-t a megbízható tartományokhoz!", "App update required" : "Alkalmazás frissítés szükséges", diff --git a/core/l10n/hu_HU.json b/core/l10n/hu_HU.json index 313be232295..b1aa5f4c8ad 100644 --- a/core/l10n/hu_HU.json +++ b/core/l10n/hu_HU.json @@ -267,6 +267,7 @@ "Contact your system administrator if this message persists or appeared unexpectedly." : "Ha ez az üzenet ismételten vagy indokolatlanul megjelenik, akkor keresse a rendszergazda segítségét!", "Thank you for your patience." : "Köszönjük a türelmét.", "You are accessing the server from an untrusted domain." : "A kiszolgálót nem megbízható tartományból éri el.", + "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." : "Kérjük keresse fel a rendszergazdát! Ha ennek a telepítésnek Ön a rendszergazdája, akkor állítsa be a config/config.php állományban a \"trusted_domain\" paramétert! A config/config.sample.php állományban talál példát a beállításra.", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "A beállításoktól függően, rendszergazdaként lehetséges, hogy az alábbi gombot is használhatja a tartomány megbízhatóvá tételéhez.", "Add \"%s\" as trusted domain" : "Adjuk hozzá \"%s\"-t a megbízható tartományokhoz!", "App update required" : "Alkalmazás frissítés szükséges", diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index e0ac89cbec8..305dea06792 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -141,7 +141,7 @@ OC.L10N.register( "Please upgrade your database version" : "Veuillez mettre à jour votre gestionnaire de base de données", "Error occurred while checking PostgreSQL version" : "Une erreur s’est produite pendant la récupération du numéro de version de PostgreSQL", "Please make sure you have PostgreSQL >= 9 or check the logs for more information about the error" : "Veuillez vérifier que vous utilisez PostgreSQL >= 9 , ou regardez dans le journal d’erreur pour plus d’informations sur ce problème", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Veuillez changer les permissions du répertoire en mode 0770 afin que son contenu puisse être listé par les autres utilisateurs.", + "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Veuillez changer les permissions du répertoire en mode 0770 afin que son contenu ne puisse pas être listé par les autres utilisateurs.", "Data directory (%s) is readable by other users" : "Le répertoire de données (%s) est lisible par les autres utilisateurs", "Data directory (%s) must be an absolute path" : "Le chemin du dossier de données (%s) doit être absolu", "Check the value of \"datadirectory\" in your configuration" : "Verifiez la valeur de \"datadirectory\" dans votre configuration", diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index 2d74c986a50..9ca7bce8d10 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -139,7 +139,7 @@ "Please upgrade your database version" : "Veuillez mettre à jour votre gestionnaire de base de données", "Error occurred while checking PostgreSQL version" : "Une erreur s’est produite pendant la récupération du numéro de version de PostgreSQL", "Please make sure you have PostgreSQL >= 9 or check the logs for more information about the error" : "Veuillez vérifier que vous utilisez PostgreSQL >= 9 , ou regardez dans le journal d’erreur pour plus d’informations sur ce problème", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Veuillez changer les permissions du répertoire en mode 0770 afin que son contenu puisse être listé par les autres utilisateurs.", + "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Veuillez changer les permissions du répertoire en mode 0770 afin que son contenu ne puisse pas être listé par les autres utilisateurs.", "Data directory (%s) is readable by other users" : "Le répertoire de données (%s) est lisible par les autres utilisateurs", "Data directory (%s) must be an absolute path" : "Le chemin du dossier de données (%s) doit être absolu", "Check the value of \"datadirectory\" in your configuration" : "Verifiez la valeur de \"datadirectory\" dans votre configuration", diff --git a/lib/l10n/hu_HU.js b/lib/l10n/hu_HU.js index d065c509460..df162844485 100644 --- a/lib/l10n/hu_HU.js +++ b/lib/l10n/hu_HU.js @@ -11,6 +11,7 @@ OC.L10N.register( "PHP with a version lower than %s is required." : "Ennél régebbi PHP szükséges: %s.", "Following databases are supported: %s" : "A következő adatbázis nem támogatott: %s", "The library %s is not available." : "A könyvtár %s nem áll rendelkezésre.", + "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.", "Help" : "Súgó", @@ -36,7 +37,9 @@ OC.L10N.register( "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.", "File name is a reserved word" : "A fajl neve egy rezervált szó", + "File name contains at least one invalid character" : "A fájlnév legalább egy érvénytelen karaktert tartalmaz!", "File name is too long" : "A fájlnév túl hosszú!", + "File is currently busy, please try again later" : "A fájl jelenleg elfoglalt, kérjük próbáld újra később!", "Can't read file" : "Nem olvasható a fájl", "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", @@ -70,25 +73,32 @@ OC.L10N.register( "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.", "Can't create or write into the data directory %s" : "Nem sikerült létrehozni vagy irni a \"data\" könyvtárba %s", + "Invalid Federated Cloud ID" : "Érvénytelen Egyesített Felhő Azonosító", "%s shared »%s« with you" : "%s megosztotta Önnel ezt: »%s«", "%s via %s" : "%s über %s", + "Sharing %s failed, because the backend does not allow shares from type %i" : "%s megosztása sikertelen, mert a megosztási alrendszer nem engedi a %l típus megosztását", "Sharing %s failed, because the file does not exist" : "%s megosztása sikertelen, mert a fájl nem létezik", "You are not allowed to share %s" : "Önnek nincs jogosultsága %s megosztására", + "Sharing %s failed, because you can not share with yourself" : "%s megosztása sikertelen, mert magaddal nem oszthatod meg", "Sharing %s failed, because the user %s does not exist" : "%s megosztása nem sikerült, mert %s felhasználó nem létezik", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s megosztása nem sikerült, mert %s felhasználó nem tagja egyik olyan csoportnak sem, aminek %s tagja", "Sharing %s failed, because this item is already shared with %s" : "%s megosztása nem sikerült, mert ez már meg van osztva %s-vel", + "Sharing %s failed, because this item is already shared with user %s" : "%s megosztása sikertelen, mert már meg van osztva %s felhasználóval", "Sharing %s failed, because the group %s does not exist" : "%s megosztása nem sikerült, mert %s csoport nem létezik", "Sharing %s failed, because %s is not a member of the group %s" : "%s megosztása nem sikerült, mert %s felhasználó nem tagja a %s csoportnak", "You need to provide a password to create a public link, only protected links are allowed" : "Meg kell adnia egy jelszót is, mert a nyilvános linkek csak jelszóval védetten használhatók", "Sharing %s failed, because sharing with links is not allowed" : "%s megosztása nem sikerült, mert a linkekkel történő megosztás nincs engedélyezve", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s megosztása sikertelen, mert %s nem található, talán a szerver jelenleg nem elérhető.", "Share type %s is not valid for %s" : "A %s megosztási típus nem érvényes %s-re", "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a megadottak túllépik a %s-re érvényes jogosultságokat", "Setting permissions for %s failed, because the item was not found" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a kérdéses állomány nem található", "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Nem lehet beállítani a lejárati időt. A megosztások legfeljebb ennyi idővel járhatnak le a létrehozásukat követően: %s", "Cannot set expiration date. Expiration date is in the past" : "Nem lehet beállítani a lejárati időt, mivel a megadott lejárati időpont már elmúlt.", + "Cannot clear expiration date. Shares are required to have an expiration date." : "Nem lehet beállítani a lejárati időt. A megosztásoknak kötelező megadni lejárati időt!", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Az %s megosztási alrendszernek támogatnia kell az OCP\\Share_Backend interface-t", "Sharing backend %s not found" : "A %s megosztási alrendszer nem található", "Sharing backend for %s not found" : "%s megosztási alrendszere nem található", + "Sharing failed, because the user %s is the original sharer" : "Megosztás sikertelen, mert %s felhasználó az eredeti megosztó", "Sharing %s failed, because the permissions exceed permissions granted to %s" : "%s megosztása nem sikerült, mert a jogosultságok túllépik azt, ami %s rendelkezésére áll", "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", @@ -111,6 +121,7 @@ OC.L10N.register( "Please install one of these locales on your system and restart your webserver." : "Kérjük állítsa be a következő lokalizációk valamelyikét a rendszeren és indítsa újra a webszervert!", "Please ask your server administrator to install the module." : "Kérje meg a rendszergazdát, hogy telepítse a modult!", "PHP module %s not installed." : "A %s PHP modul nincs telepítve.", + "PHP setting \"%s\" is not set to \"%s\"." : "%s PHP beállítás nincs \"%s\"-re állítva.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Ezt valószínűleg egy gyorsítótár ill. kódgyorsító, mint pl, a Zend, OPcache vagy eAccelererator okozza.", "PHP modules have been installed, but they are still listed as missing?" : "A PHP modulok telepítve vannak, de a listában mégsincsenek felsorolva?", "Please ask your server administrator to restart the web server." : "Kérje meg a rendszergazdát, hogy indítsa újra a webszervert!", @@ -120,6 +131,7 @@ OC.L10N.register( "Please make sure you have PostgreSQL >= 9 or check the logs for more information about the error" : "Kérjük gondoskodjon róla, hogy a PostgreSQL legalább 9-es verziójú legyen, vagy ellenőrizze a naplófájlokat, hogy mi okozta a hibát!", "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Kérjük módosítsa a könyvtár elérhetőségi engedélybeállítását 0770-re, hogy a tartalmát más felhasználó ne listázhassa!", "Data directory (%s) is readable by other users" : "Az adatkönyvtár (%s) más felhasználók számára is olvasható ", + "Data directory (%s) must be an absolute path" : "Az adatkönyvtárnak (%s) abszolút elérési útnak kell lennie", "Data directory (%s) is invalid" : "Érvénytelen a megadott adatkönyvtár (%s) ", "Please check that the data directory contains a file \".ocdata\" in its root." : "Kérjük ellenőrizze, hogy az adatkönyvtár tartalmaz a gyökerében egy \".ocdata\" nevű állományt!", "Could not obtain lock type %d on \"%s\"." : "Nem sikerült %d típusú zárolást elérni itt: \"%s\".", diff --git a/lib/l10n/hu_HU.json b/lib/l10n/hu_HU.json index 4f864c1d75d..a94321be0b6 100644 --- a/lib/l10n/hu_HU.json +++ b/lib/l10n/hu_HU.json @@ -9,6 +9,7 @@ "PHP with a version lower than %s is required." : "Ennél régebbi PHP szükséges: %s.", "Following databases are supported: %s" : "A következő adatbázis nem támogatott: %s", "The library %s is not available." : "A könyvtár %s nem áll rendelkezésre.", + "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.", "Help" : "Súgó", @@ -34,7 +35,9 @@ "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.", "File name is a reserved word" : "A fajl neve egy rezervált szó", + "File name contains at least one invalid character" : "A fájlnév legalább egy érvénytelen karaktert tartalmaz!", "File name is too long" : "A fájlnév túl hosszú!", + "File is currently busy, please try again later" : "A fájl jelenleg elfoglalt, kérjük próbáld újra később!", "Can't read file" : "Nem olvasható a fájl", "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", @@ -68,25 +71,32 @@ "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.", "Can't create or write into the data directory %s" : "Nem sikerült létrehozni vagy irni a \"data\" könyvtárba %s", + "Invalid Federated Cloud ID" : "Érvénytelen Egyesített Felhő Azonosító", "%s shared »%s« with you" : "%s megosztotta Önnel ezt: »%s«", "%s via %s" : "%s über %s", + "Sharing %s failed, because the backend does not allow shares from type %i" : "%s megosztása sikertelen, mert a megosztási alrendszer nem engedi a %l típus megosztását", "Sharing %s failed, because the file does not exist" : "%s megosztása sikertelen, mert a fájl nem létezik", "You are not allowed to share %s" : "Önnek nincs jogosultsága %s megosztására", + "Sharing %s failed, because you can not share with yourself" : "%s megosztása sikertelen, mert magaddal nem oszthatod meg", "Sharing %s failed, because the user %s does not exist" : "%s megosztása nem sikerült, mert %s felhasználó nem létezik", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s megosztása nem sikerült, mert %s felhasználó nem tagja egyik olyan csoportnak sem, aminek %s tagja", "Sharing %s failed, because this item is already shared with %s" : "%s megosztása nem sikerült, mert ez már meg van osztva %s-vel", + "Sharing %s failed, because this item is already shared with user %s" : "%s megosztása sikertelen, mert már meg van osztva %s felhasználóval", "Sharing %s failed, because the group %s does not exist" : "%s megosztása nem sikerült, mert %s csoport nem létezik", "Sharing %s failed, because %s is not a member of the group %s" : "%s megosztása nem sikerült, mert %s felhasználó nem tagja a %s csoportnak", "You need to provide a password to create a public link, only protected links are allowed" : "Meg kell adnia egy jelszót is, mert a nyilvános linkek csak jelszóval védetten használhatók", "Sharing %s failed, because sharing with links is not allowed" : "%s megosztása nem sikerült, mert a linkekkel történő megosztás nincs engedélyezve", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s megosztása sikertelen, mert %s nem található, talán a szerver jelenleg nem elérhető.", "Share type %s is not valid for %s" : "A %s megosztási típus nem érvényes %s-re", "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a megadottak túllépik a %s-re érvényes jogosultságokat", "Setting permissions for %s failed, because the item was not found" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a kérdéses állomány nem található", "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Nem lehet beállítani a lejárati időt. A megosztások legfeljebb ennyi idővel járhatnak le a létrehozásukat követően: %s", "Cannot set expiration date. Expiration date is in the past" : "Nem lehet beállítani a lejárati időt, mivel a megadott lejárati időpont már elmúlt.", + "Cannot clear expiration date. Shares are required to have an expiration date." : "Nem lehet beállítani a lejárati időt. A megosztásoknak kötelező megadni lejárati időt!", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Az %s megosztási alrendszernek támogatnia kell az OCP\\Share_Backend interface-t", "Sharing backend %s not found" : "A %s megosztási alrendszer nem található", "Sharing backend for %s not found" : "%s megosztási alrendszere nem található", + "Sharing failed, because the user %s is the original sharer" : "Megosztás sikertelen, mert %s felhasználó az eredeti megosztó", "Sharing %s failed, because the permissions exceed permissions granted to %s" : "%s megosztása nem sikerült, mert a jogosultságok túllépik azt, ami %s rendelkezésére áll", "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", @@ -109,6 +119,7 @@ "Please install one of these locales on your system and restart your webserver." : "Kérjük állítsa be a következő lokalizációk valamelyikét a rendszeren és indítsa újra a webszervert!", "Please ask your server administrator to install the module." : "Kérje meg a rendszergazdát, hogy telepítse a modult!", "PHP module %s not installed." : "A %s PHP modul nincs telepítve.", + "PHP setting \"%s\" is not set to \"%s\"." : "%s PHP beállítás nincs \"%s\"-re állítva.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Ezt valószínűleg egy gyorsítótár ill. kódgyorsító, mint pl, a Zend, OPcache vagy eAccelererator okozza.", "PHP modules have been installed, but they are still listed as missing?" : "A PHP modulok telepítve vannak, de a listában mégsincsenek felsorolva?", "Please ask your server administrator to restart the web server." : "Kérje meg a rendszergazdát, hogy indítsa újra a webszervert!", @@ -118,6 +129,7 @@ "Please make sure you have PostgreSQL >= 9 or check the logs for more information about the error" : "Kérjük gondoskodjon róla, hogy a PostgreSQL legalább 9-es verziójú legyen, vagy ellenőrizze a naplófájlokat, hogy mi okozta a hibát!", "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Kérjük módosítsa a könyvtár elérhetőségi engedélybeállítását 0770-re, hogy a tartalmát más felhasználó ne listázhassa!", "Data directory (%s) is readable by other users" : "Az adatkönyvtár (%s) más felhasználók számára is olvasható ", + "Data directory (%s) must be an absolute path" : "Az adatkönyvtárnak (%s) abszolút elérési útnak kell lennie", "Data directory (%s) is invalid" : "Érvénytelen a megadott adatkönyvtár (%s) ", "Please check that the data directory contains a file \".ocdata\" in its root." : "Kérjük ellenőrizze, hogy az adatkönyvtár tartalmaz a gyökerében egy \".ocdata\" nevű állományt!", "Could not obtain lock type %d on \"%s\"." : "Nem sikerült %d típusú zárolást elérni itt: \"%s\".", diff --git a/settings/l10n/zh_TW.js b/settings/l10n/zh_TW.js index caa85e2b443..b59605da676 100644 --- a/settings/l10n/zh_TW.js +++ b/settings/l10n/zh_TW.js @@ -229,7 +229,7 @@ OC.L10N.register( "iOS app" : "iOS 應用程式", "If you want to support the project\n\t\tjoin development\n\t\tor\n\t\tspread the word!" : "若您想支援這個計畫\n\t\t加入開發者\n\t\t或\n\t\t替我們宣傳!", "Show First Run Wizard again" : "再次顯示首次使用精靈", - "You have used %s of the available %s" : "您已經使用了 %s ,目前可用空間為 %s", + "You have used %s of the available %s" : "您已經使用了 %s ,總共可用空間為 %s", "Password" : "密碼", "Unable to change your password" : "無法變更您的密碼", "Current password" : "目前密碼", diff --git a/settings/l10n/zh_TW.json b/settings/l10n/zh_TW.json index 2d7951b8930..9e1e42455df 100644 --- a/settings/l10n/zh_TW.json +++ b/settings/l10n/zh_TW.json @@ -227,7 +227,7 @@ "iOS app" : "iOS 應用程式", "If you want to support the project\n\t\tjoin development\n\t\tor\n\t\tspread the word!" : "若您想支援這個計畫\n\t\t加入開發者\n\t\t或\n\t\t替我們宣傳!", "Show First Run Wizard again" : "再次顯示首次使用精靈", - "You have used %s of the available %s" : "您已經使用了 %s ,目前可用空間為 %s", + "You have used %s of the available %s" : "您已經使用了 %s ,總共可用空間為 %s", "Password" : "密碼", "Unable to change your password" : "無法變更您的密碼", "Current password" : "目前密碼", -- GitLab From 1189528e1ff84542ae6c8fe32654a979b954e7cd Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Thu, 19 Nov 2015 09:11:14 +0100 Subject: [PATCH 071/344] Always installed apps includes the hardcoded ones from shipped.json * fixes #20568 --- lib/private/app/appmanager.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/private/app/appmanager.php b/lib/private/app/appmanager.php index 1f993d8538f..f826c8ba0c7 100644 --- a/lib/private/app/appmanager.php +++ b/lib/private/app/appmanager.php @@ -77,6 +77,12 @@ class AppManager implements IAppManager { private function getInstalledAppsValues() { if (!$this->installedAppsCache) { $values = $this->appConfig->getValues(false, 'enabled'); + + $alwaysEnabledApps = $this->getAlwaysEnabledApps(); + foreach($alwaysEnabledApps as $appId) { + $values[$appId] = 'yes'; + } + $this->installedAppsCache = array_filter($values, function ($value) { return $value !== 'no'; }); -- GitLab From 0b8335ff2f80df53f4acf7ef5e4501f83c9012f5 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 19 Nov 2015 09:25:34 +0100 Subject: [PATCH 072/344] Make the JobList test more robust by sorting the result of getAll before comparison --- tests/lib/backgroundjob/joblist.php | 36 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/lib/backgroundjob/joblist.php b/tests/lib/backgroundjob/joblist.php index d5136676a47..b329c83009b 100644 --- a/tests/lib/backgroundjob/joblist.php +++ b/tests/lib/backgroundjob/joblist.php @@ -8,6 +8,8 @@ namespace Test\BackgroundJob; +use OCP\BackgroundJob\IJob; + class JobList extends \Test\TestCase { /** * @var \OC\BackgroundJob\JobList @@ -27,6 +29,16 @@ class JobList extends \Test\TestCase { $this->instance = new \OC\BackgroundJob\JobList($conn, $this->config); } + protected function getAllSorted() { + $jobs = $this->instance->getAll(); + + usort($jobs, function (IJob $job1, IJob $job2) { + return $job1->getId() - $job2->getId(); + }); + + return $jobs; + } + public function argumentProvider() { return array( array(null), @@ -45,11 +57,11 @@ class JobList extends \Test\TestCase { * @param $argument */ public function testAddRemove($argument) { - $existingJobs = $this->instance->getAll(); + $existingJobs = $this->getAllSorted(); $job = new TestJob(); $this->instance->add($job, $argument); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $this->assertCount(count($existingJobs) + 1, $jobs); $addedJob = $jobs[count($jobs) - 1]; @@ -58,7 +70,7 @@ class JobList extends \Test\TestCase { $this->instance->remove($job, $argument); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $this->assertEquals($existingJobs, $jobs); } @@ -67,19 +79,19 @@ class JobList extends \Test\TestCase { * @param $argument */ public function testRemoveDifferentArgument($argument) { - $existingJobs = $this->instance->getAll(); + $existingJobs = $this->getAllSorted(); $job = new TestJob(); $this->instance->add($job, $argument); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $this->instance->remove($job, 10); - $jobs2 = $this->instance->getAll(); + $jobs2 = $this->getAllSorted(); $this->assertEquals($jobs, $jobs2); $this->instance->remove($job, $argument); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $this->assertEquals($existingJobs, $jobs); } @@ -126,7 +138,7 @@ class JobList extends \Test\TestCase { $this->instance->add($job, 1); $this->instance->add($job, 2); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $savedJob1 = $jobs[count($jobs) - 2]; $savedJob2 = $jobs[count($jobs) - 1]; @@ -149,7 +161,7 @@ class JobList extends \Test\TestCase { $this->instance->add($job, 1); $this->instance->add($job, 2); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $savedJob2 = $jobs[count($jobs) - 1]; @@ -174,7 +186,7 @@ class JobList extends \Test\TestCase { $job = new TestJob(); $this->instance->add($job, $argument); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $addedJob = $jobs[count($jobs) - 1]; @@ -187,7 +199,7 @@ class JobList extends \Test\TestCase { $job = new TestJob(); $this->instance->add($job); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $addedJob = $jobs[count($jobs) - 1]; @@ -209,7 +221,7 @@ class JobList extends \Test\TestCase { $this->instance->add('\OC\Non\Existing\Class'); $this->instance->add($job, 2); - $jobs = $this->instance->getAll(); + $jobs = $this->getAllSorted(); $savedJob1 = $jobs[count($jobs) - 2]; $savedJob2 = $jobs[count($jobs) - 1]; -- GitLab From ea6341df296b86cfa6960d7c2d404e4c77d19506 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 17 Nov 2015 17:01:53 +0100 Subject: [PATCH 073/344] Core interfaces for system tags and its manager --- lib/public/systemtag/isystemtag.php | 68 +++++++++++ .../systemtag/isystemtagobjectmapper.php | 115 ++++++++++++++++++ lib/public/systemtag/isystemtagsmanager.php | 111 +++++++++++++++++ .../systemtag/tagalreadyexistsexception.php | 29 +++++ lib/public/systemtag/tagnotfoundexception.php | 29 +++++ 5 files changed, 352 insertions(+) create mode 100644 lib/public/systemtag/isystemtag.php create mode 100644 lib/public/systemtag/isystemtagobjectmapper.php create mode 100644 lib/public/systemtag/isystemtagsmanager.php create mode 100644 lib/public/systemtag/tagalreadyexistsexception.php create mode 100644 lib/public/systemtag/tagnotfoundexception.php diff --git a/lib/public/systemtag/isystemtag.php b/lib/public/systemtag/isystemtag.php new file mode 100644 index 00000000000..76a812f38dc --- /dev/null +++ b/lib/public/systemtag/isystemtag.php @@ -0,0 +1,68 @@ + + * + * @copyright Copyright (c) 2015, 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 OCP\SystemTag; + +/** + * Public interface for a system-wide tag. + * + * @since 9.0.0 + */ +interface ISystemTag { + + /** + * Returns the tag id + * + * @return string id + * + * @since 9.0.0 + */ + public function getId(); + + /** + * Returns the tag display name + * + * @return string tag display name + * + * @since 9.0.0 + */ + public function getName(); + + /** + * Returns whether the tag is visible for regular users + * + * @return bool true if visible, false otherwise + * + * @since 9.0.0 + */ + public function isUserVisible(); + + /** + * Returns whether the tag can be assigned to objects by regular users + * + * @return bool true if assignable, false otherwise + * + * @since 9.0.0 + */ + public function isUserAsssignable(); + +} + diff --git a/lib/public/systemtag/isystemtagobjectmapper.php b/lib/public/systemtag/isystemtagobjectmapper.php new file mode 100644 index 00000000000..87f3fd0473f --- /dev/null +++ b/lib/public/systemtag/isystemtagobjectmapper.php @@ -0,0 +1,115 @@ + + * + * @copyright Copyright (c) 2015, 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 OCP\SystemTag; + +/** + * Public interface to access and manage system-wide tags. + * + * @since 9.0.0 + */ +interface ISystemTagObjectMapper { + + /** + * Get a list of tag ids for the given object ids. + * + * This returns an array that maps object id to tag ids + * [ + * 1 => array('id1', 'id2'), + * 2 => array('id3', 'id2'), + * 3 => array('id5'), + * 4 => array() + * ] + * + * Untagged objects will have an empty array associated. + * + * @param string|array $objIds object ids + * @param string $objectType object type + * + * @return array with object id as key and an array + * of tag ids as value + * + * @since 9.0.0 + */ + public function getTagIdsForObjects($objIds, $objectType); + + /** + * Get a list of objects tagged with $tagIds. + * + * @param string|array $tagIds Tag id or array of tag ids. + * @param string $objectType object type + * + * @return string[] array of object ids or empty array if none found + * + * @throws \OCP\SystemTag\TagNotFoundException if at least one of the + * given tags does not exist + * + * @since 9.0.0 + */ + public function getObjectIdsForTags($tagIds, $objectType); + + /** + * Assign the given tags to the given object. + * + * @param string $objId object id + * @param string $objectType object type + * @param string|array $tagIds tag id or array of tag ids to assign + * + * @throws \OCP\SystemTag\TagNotFoundException if at least one of the + * given tags does not exist + * + * @since 9.0.0 + */ + public function assignTags($objId, $objectType, $tagIds); + + /** + * Unassign the given tags from the given object. + * + * @param string $objId object id + * @param string $objectType object type + * @param string|array $tagIds tag id or array of tag ids to unassign + * + * @throws \OCP\SystemTag\TagNotFoundException if at least one of the + * given tags does not exist + * + * @since 9.0.0 + */ + public function unassignTags($objId, $objectType, $tagIds); + + /** + * Checks whether the given objects have the given tag. + * + * @param string|array $objIds object ids + * @param string $objectType object type + * @param string $tagId tag id to check + * @param bool $all true to check that ALL objects have the tag assigned, + * false to check that at least ONE object has the tag. + * + * @return bool true if the condition set by $all is matched, false + * otherwise + * + * @throws \OCP\SystemTag\TagNotFoundException if the tag does not exist + * + * @since 9.0.0 + */ + public function hasTags($objIds, $objectType, $tagId, $all = true); + +} diff --git a/lib/public/systemtag/isystemtagsmanager.php b/lib/public/systemtag/isystemtagsmanager.php new file mode 100644 index 00000000000..df59cc48d52 --- /dev/null +++ b/lib/public/systemtag/isystemtagsmanager.php @@ -0,0 +1,111 @@ + + * + * @copyright Copyright (c) 2015, 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 OCP\SystemTag; + +/** + * Public interface to access and manage system-wide tags. + * + * @since 9.0.0 + */ +interface ISystemTagManager { + + /** + * Returns the tag objects matching the given tag ids. + * + * @param array|string $tagIds The ID or array of IDs of the tags to retrieve + * + * @return \OCP\SystemTag\ISystemTag[] array of system tags or empty array if none found + * + * @since 9.0.0 + */ + public function getTagsById($tagIds); + + /** + * Returns the tag object matching the given attributes. + * + * @param string $tagName tag name + * @param bool $userVisible whether the tag is visible by users + * @param bool $userAssignable whether the tag is assignable by users + * + * @return \OCP\SystemTag\ISystemTag system tag + * + * @throws \OCP\SystemTag\TagNotFoundException if tag does not exist + * + * @since 9.0.0 + */ + public function getTag($tagName, $userVisible, $userAssignable); + + /** + * Creates the tag object using the given attributes. + * + * @param string $tagName tag name + * @param bool $userVisible whether the tag is visible by users + * @param bool $userAssignable whether the tag is assignable by users + * + * @return \OCP\SystemTag\ISystemTag system tag + * + * @throws \OCP\SystemTag\TagAlreadyExistsException if tag already exists + * + * @since 9.0.0 + */ + public function createTag($tagName, $userVisible, $userAssignable); + + /** + * Returns all known tags, optionally filtered by visibility. + * + * @param bool $visibleOnly whether to only return user visible tags + * @param string $nameSearchPattern optional search pattern for the tag name + * + * @return \OCP\SystemTag\ISystemTag[] array of system tags or empty array if none found + * + * @since 9.0.0 + */ + public function getAllTags($visibleOnly = false, $nameSearchPattern = null); + + /** + * Updates the given tag + * + * @param string $tagId tag id + * @param string $newName the new tag name + * @param bool $userVisible whether the tag is visible by users + * @param bool $userAssignable whether the tag is assignable by users + * + * @throws \OCP\SystemTag\TagNotFoundException if tag with the given id does not exist + * @throws \OCP\SystemTag\TagAlreadyExistsException if there is already another tag + * with the same attributes + * + * @since 9.0.0 + */ + public function updateTag($tagId, $newName, $userVisible, $userAssignable); + + /** + * Delete the given tags from the database and all their relationships. + * + * @param string|array $tagIds array of tag ids + * + * @throws \OCP\SystemTag\TagNotFoundException if tag did not exist + * + * @since 9.0.0 + */ + public function deleteTags($tagIds); + +} diff --git a/lib/public/systemtag/tagalreadyexistsexception.php b/lib/public/systemtag/tagalreadyexistsexception.php new file mode 100644 index 00000000000..d192b38e7bc --- /dev/null +++ b/lib/public/systemtag/tagalreadyexistsexception.php @@ -0,0 +1,29 @@ + + * + * @copyright Copyright (c) 2015, 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 OCP\SystemTag; + +/** + * Exception when a tag already exists. + * + * @since 9.0.0 + */ +class TagAlreadyExistsException extends \RuntimeException {} diff --git a/lib/public/systemtag/tagnotfoundexception.php b/lib/public/systemtag/tagnotfoundexception.php new file mode 100644 index 00000000000..94bb07c8c12 --- /dev/null +++ b/lib/public/systemtag/tagnotfoundexception.php @@ -0,0 +1,29 @@ + + * + * @copyright Copyright (c) 2015, 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 OCP\SystemTag; + +/** + * Exception when a tag was not found. + * + * @since 9.0.0 + */ +class TagNotFoundException extends \RuntimeException {} -- GitLab From 4eb15885c9a7e930670ed58af2e566c1928bc059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 5 Nov 2015 16:46:37 +0100 Subject: [PATCH 074/344] Addressbook sharing added based on a simplified approach which is based on calendar sharing standard --- apps/dav/appinfo/database.xml | 51 +++++ apps/dav/lib/carddav/addressbook.php | 58 ++++++ apps/dav/lib/carddav/addressbookroot.php | 23 +++ apps/dav/lib/carddav/carddavbackend.php | 159 +++++++++++++- .../carddav/sharing/ishareableaddressbook.php | 46 +++++ apps/dav/lib/carddav/sharing/plugin.php | 194 ++++++++++++++++++ apps/dav/lib/carddav/useraddressbooks.php | 23 +++ apps/dav/lib/rootcollection.php | 6 +- apps/dav/tests/misc/sharing.xml | 7 + .../tests/unit/carddav/carddavbackendtest.php | 43 +++- 10 files changed, 605 insertions(+), 5 deletions(-) create mode 100644 apps/dav/lib/carddav/addressbook.php create mode 100644 apps/dav/lib/carddav/addressbookroot.php create mode 100644 apps/dav/lib/carddav/sharing/ishareableaddressbook.php create mode 100644 apps/dav/lib/carddav/sharing/plugin.php create mode 100644 apps/dav/lib/carddav/useraddressbooks.php create mode 100644 apps/dav/tests/misc/sharing.xml diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml index 5e2dad097e4..48641c2be6f 100644 --- a/apps/dav/appinfo/database.xml +++ b/apps/dav/appinfo/database.xml @@ -570,4 +570,55 @@ CREATE TABLE calendarobjects (
+ + + *dbprefix*dav_shares + + + id + integer + 0 + true + 1 + true + 11 + + + uri + text + + + principaluri + text + + + type + text + + + access + integer + 1 + + + resourceid + integer + true + true + + + dav_shares_index + true + + principaluri + + + uri + + + type + + + +
diff --git a/apps/dav/lib/carddav/addressbook.php b/apps/dav/lib/carddav/addressbook.php new file mode 100644 index 00000000000..e50f6f4adf6 --- /dev/null +++ b/apps/dav/lib/carddav/addressbook.php @@ -0,0 +1,58 @@ +carddavBackend; + $carddavBackend->updateShares($this->getName(), $add, $remove); + } + + /** + * Returns the list of people whom this addressbook is shared with. + * + * Every element in this array should have the following properties: + * * href - Often a mailto: address + * * commonName - Optional, for example a first + last name + * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. + * * readOnly - boolean + * * summary - Optional, a description for the share + * + * @return array + */ + function getShares() { + /** @var CardDavBackend $carddavBackend */ + $carddavBackend = $this->carddavBackend; + $carddavBackend->getShares($this->getName()); + } +} \ No newline at end of file diff --git a/apps/dav/lib/carddav/addressbookroot.php b/apps/dav/lib/carddav/addressbookroot.php new file mode 100644 index 00000000000..ee99ac8d798 --- /dev/null +++ b/apps/dav/lib/carddav/addressbookroot.php @@ -0,0 +1,23 @@ +carddavBackend, $principal['uri']); + + } + +} \ No newline at end of file diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index b2597baedc6..3af70571610 100644 --- a/apps/dav/lib/carddav/carddavbackend.php +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -22,6 +22,7 @@ namespace OCA\DAV\CardDAV; +use OCA\DAV\Connector\Sabre\Principal; use Sabre\CardDAV\Backend\BackendInterface; use Sabre\CardDAV\Backend\SyncSupport; use Sabre\CardDAV\Plugin; @@ -29,8 +30,12 @@ use Sabre\DAV\Exception\BadRequest; class CardDavBackend implements BackendInterface, SyncSupport { - public function __construct(\OCP\IDBConnection $db) { + /** @var Principal */ + private $principalBackend; + + public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) { $this->db = $db; + $this->principalBackend = $principalBackend; } /** @@ -73,9 +78,61 @@ class CardDavBackend implements BackendInterface, SyncSupport { } $result->closeCursor(); + // query for shared calendars + $query = $this->db->getQueryBuilder(); + $query2 = $this->db->getQueryBuilder(); + $query2->select(['resourceid']) + ->from('dav_shares') + ->where($query2->expr()->eq('principaluri', $query2->createParameter('principaluri'))) + ->andWhere($query2->expr()->eq('type', $query2->createParameter('type'))); + $result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken']) + ->from('addressbooks') + ->where($query->expr()->in('id', $query->createFunction($query2->getSQL()))) + ->setParameter('type', 'addressbook') + ->setParameter('principaluri', $principalUri) + ->execute(); + + while($row = $result->fetch()) { + $addressBooks[] = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'principaluri' => $row['principaluri'], + '{DAV:}displayname' => $row['displayname'], + '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], + '{http://calendarserver.org/ns/}getctag' => $row['synctoken'], + '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', + ]; + } + $result->closeCursor(); + return $addressBooks; } + private function getAddressBooksByUri($addressBookUri) { + $query = $this->db->getQueryBuilder(); + $result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken']) + ->from('addressbooks') + ->where($query->expr()->eq('uri', $query->createNamedParameter($addressBookUri))) + ->setMaxResults(1) + ->execute(); + + $row = $result->fetch(); + if (is_null($row)) { + return null; + } + $result->closeCursor(); + + return [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'principaluri' => $row['principaluri'], + '{DAV:}displayname' => $row['displayname'], + '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], + '{http://calendarserver.org/ns/}getctag' => $row['synctoken'], + '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', + ]; + } + /** * Updates properties for an address book. * @@ -201,6 +258,11 @@ class CardDavBackend implements BackendInterface, SyncSupport { ->where($query->expr()->eq('id', $query->createParameter('id'))) ->setParameter('id', $addressBookId) ->execute(); + + $query->delete('dav_shares') + ->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBookId))) + ->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook'))) + ->execute(); } /** @@ -561,4 +623,99 @@ class CardDavBackend implements BackendInterface, SyncSupport { return $cardData; } + public function updateShares($path, $add, $remove) { + foreach($add as $element) { + $this->shareWith($path, $element); + } + foreach($remove as $element) { + $this->unshare($path, $element); + } + } + + private function shareWith($addressBookUri, $element) { + $user = $element['href']; + $parts = explode(':', $user, 2); + if ($parts[0] !== 'principal') { + return; + } + $p = $this->principalBackend->getPrincipalByPath($parts[1]); + if (is_null($p)) { + return; + } + + $addressbook = $this->getAddressBooksByUri($addressBookUri); + if (is_null($addressbook)) { + return; + } + + $query = $this->db->getQueryBuilder(); + $query->insert('dav_shares') + ->values([ + 'principaluri' => $query->createNamedParameter($parts[1]), + 'uri' => $query->createNamedParameter($addressBookUri), + 'type' => $query->createNamedParameter('addressbook'), + 'access' => $query->createNamedParameter(0), + 'resourceid' => $query->createNamedParameter($addressbook['id']) + ]); + $query->execute(); + } + + private function unshare($addressBookUri, $element) { + $user = $element['href']; + $parts = explode(':', $user, 2); + if ($parts[0] !== 'principal') { + return; + } + $p = $this->principalBackend->getPrincipalByPath($parts[1]); + if (is_null($p)) { + return; + } + + $addressbook = $this->getAddressBooksByUri($addressBookUri); + if (is_null($addressbook)) { + return; + } + + $query = $this->db->getQueryBuilder(); + $query->delete('dav_shares') + ->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressbook['id']))) + ->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook'))) + ->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($parts[1]))) + ; + $query->execute(); + } + + /** + * Returns the list of people whom this addressbook is shared with. + * + * Every element in this array should have the following properties: + * * href - Often a mailto: address + * * commonName - Optional, for example a first + last name + * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. + * * readOnly - boolean + * * summary - Optional, a description for the share + * + * @return array + */ + public function getShares($addressBookUri) { + $query = $this->db->getQueryBuilder(); + $result = $query->select(['principaluri', 'access']) + ->from('dav_shares') + ->where($query->expr()->eq('uri', $query->createNamedParameter($addressBookUri))) + ->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook'))) + ->execute(); + + $shares = []; + while($row = $result->fetch()) { + $p = $this->principalBackend->getPrincipalByPath($row['principaluri']); + $shares[]= [ + 'href' => "principal:${p['uri']}", + 'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '', + 'status' => 1, + 'readOnly' => ($row['access'] === 1) + ]; + } + + return $shares; + } } diff --git a/apps/dav/lib/carddav/sharing/ishareableaddressbook.php b/apps/dav/lib/carddav/sharing/ishareableaddressbook.php new file mode 100644 index 00000000000..856a9ed18e6 --- /dev/null +++ b/apps/dav/lib/carddav/sharing/ishareableaddressbook.php @@ -0,0 +1,46 @@ +server = $server; + $server->resourceTypeMapping['OCA\\DAV\CardDAV\\ISharedAddressbook'] = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}shared'; + + $this->server->on('method:POST', [$this, 'httpPost']); + } + + /** + * We intercept this to handle POST requests on calendars. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return null|bool + */ + function httpPost(RequestInterface $request, ResponseInterface $response) { + + $path = $request->getPath(); + + // Only handling xml + $contentType = $request->getHeader('Content-Type'); + if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) + return; + + // Making sure the node exists + try { + $node = $this->server->tree->getNodeForPath($path); + } catch (NotFound $e) { + return; + } + + $requestBody = $request->getBodyAsString(); + + // If this request handler could not deal with this POST request, it + // will return 'null' and other plugins get a chance to handle the + // request. + // + // However, we already requested the full body. This is a problem, + // because a body can only be read once. This is why we preemptively + // re-populated the request body with the existing data. + $request->setBody($requestBody); + + $dom = XMLUtil::loadDOMDocument($requestBody); + + $documentType = XMLUtil::toClarkNotation($dom->firstChild); + + switch ($documentType) { + + // Dealing with the 'share' document, which modified invitees on a + // calendar. + case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share' : + + // We can only deal with IShareableCalendar objects + if (!$node instanceof IShareableAddressBook) { + return; + } + + $this->server->transactionType = 'post-calendar-share'; + + // Getting ACL info + $acl = $this->server->getPlugin('acl'); + + // If there's no ACL support, we allow everything + if ($acl) { + $acl->checkPrivileges($path, '{DAV:}write'); + } + + $mutations = $this->parseShareRequest($dom); + + $node->updateShares($mutations[0], $mutations[1]); + + $response->setStatus(200); + // Adding this because sending a response body may cause issues, + // and I wanted some type of indicator the response was handled. + $response->setHeader('X-Sabre-Status', 'everything-went-well'); + + // Breaking the event chain + return false; + } + } + + /** + * Parses the 'share' POST request. + * + * This method returns an array, containing two arrays. + * The first array is a list of new sharees. Every element is a struct + * containing a: + * * href element. (usually a mailto: address) + * * commonName element (often a first and lastname, but can also be + * false) + * * readOnly (true or false) + * * summary (A description of the share, can also be false) + * + * The second array is a list of sharees that are to be removed. This is + * just a simple array with 'hrefs'. + * + * @param \DOMDocument $dom + * @return array + */ + function parseShareRequest(\DOMDocument $dom) { + + $xpath = new \DOMXPath($dom); + $xpath->registerNamespace('cs', \Sabre\CardDAV\Plugin::NS_CARDDAV); + $xpath->registerNamespace('d', 'urn:DAV'); + + $set = []; + $elems = $xpath->query('cs:set'); + + for ($i = 0; $i < $elems->length; $i++) { + + $xset = $elems->item($i); + $set[] = [ + 'href' => $xpath->evaluate('string(d:href)', $xset), + 'commonName' => $xpath->evaluate('string(cs:common-name)', $xset), + 'summary' => $xpath->evaluate('string(cs:summary)', $xset), + 'readOnly' => $xpath->evaluate('boolean(cs:read)', $xset) !== false + ]; + + } + + $remove = []; + $elems = $xpath->query('cs:remove'); + + for ($i = 0; $i < $elems->length; $i++) { + + $xremove = $elems->item($i); + $remove[] = $xpath->evaluate('string(d:href)', $xremove); + + } + + return [$set, $remove]; + + } + + +} diff --git a/apps/dav/lib/carddav/useraddressbooks.php b/apps/dav/lib/carddav/useraddressbooks.php new file mode 100644 index 00000000000..adbb0292fa7 --- /dev/null +++ b/apps/dav/lib/carddav/useraddressbooks.php @@ -0,0 +1,23 @@ +carddavBackend->getAddressBooksForUser($this->principalUri); + $objs = []; + foreach($addressbooks as $addressbook) { + $objs[] = new AddressBook($this->carddavBackend, $addressbook); + } + return $objs; + + } + +} diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php index 10baff072cc..672e0a98684 100644 --- a/apps/dav/lib/rootcollection.php +++ b/apps/dav/lib/rootcollection.php @@ -3,11 +3,11 @@ namespace OCA\DAV; use OCA\DAV\CalDAV\CalDavBackend; +use OCA\DAV\CardDAV\AddressBookRoot; use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\Connector\Sabre\Principal; use Sabre\CalDAV\CalendarRoot; use Sabre\CalDAV\Principal\Collection; -use Sabre\CardDAV\AddressBookRoot; use Sabre\DAV\SimpleCollection; class RootCollection extends SimpleCollection { @@ -30,7 +30,9 @@ class RootCollection extends SimpleCollection { $caldavBackend = new CalDavBackend($db); $calendarRoot = new CalendarRoot($principalBackend, $caldavBackend); $calendarRoot->disableListing = $disableListing; - $cardDavBackend = new CardDavBackend($db); + + $cardDavBackend = new CardDavBackend(\OC::$server->getDatabaseConnection(), $principalBackend); + $addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend); $addressBookRoot->disableListing = $disableListing; diff --git a/apps/dav/tests/misc/sharing.xml b/apps/dav/tests/misc/sharing.xml new file mode 100644 index 00000000000..8771256ce79 --- /dev/null +++ b/apps/dav/tests/misc/sharing.xml @@ -0,0 +1,7 @@ + + + + principal:principals/admin + + + diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php index 79ef36d8097..d76db5a91e2 100644 --- a/apps/dav/tests/unit/carddav/carddavbackendtest.php +++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php @@ -24,6 +24,13 @@ use OCA\DAV\CardDAV\CardDavBackend; use Sabre\DAV\PropPatch; use Test\TestCase; +/** + * Class CardDavBackendTest + * + * @group DB + * + * @package OCA\DAV\Tests\Unit\CardDAV + */ class CardDavBackendTest extends TestCase { /** @var CardDavBackend */ @@ -31,12 +38,20 @@ class CardDavBackendTest extends TestCase { const UNIT_TEST_USER = 'carddav-unit-test'; - public function setUp() { parent::setUp(); + $principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal') + ->disableOriginalConstructor() + ->setMethods(['getPrincipalByPath']) + ->getMock(); + $principal->method('getPrincipalByPath') + ->willReturn([ + 'uri' => 'principals/best-friend' + ]); + $db = \OC::$server->getDatabaseConnection(); - $this->backend = new CardDavBackend($db); + $this->backend = new CardDavBackend($db, $principal); $this->tearDown(); } @@ -178,4 +193,28 @@ class CardDavBackendTest extends TestCase { $changes = $this->backend->getChangesForAddressBook($bookId, $syncToken, 1); $this->assertEquals($uri0, $changes['added'][0]); } + + public function testSharing() { + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + + $this->backend->updateShares('Example', [['href' => 'principal:principals/best-friend']], []); + + $shares = $this->backend->getShares('Example'); + $this->assertEquals(1, count($shares)); + + $books = $this->backend->getAddressBooksForUser('principals/best-friend'); + $this->assertEquals(1, count($books)); + + $this->backend->updateShares('Example', [], [['href' => 'principal:principals/best-friend']]); + + $shares = $this->backend->getShares('Example'); + $this->assertEquals(0, count($shares)); + + $books = $this->backend->getAddressBooksForUser('principals/best-friend'); + $this->assertEquals(0, count($books)); + + + } } -- GitLab From 0f434e0b9b2762de663f9a0a2930f9fdc3c23ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 10 Nov 2015 07:54:35 +0100 Subject: [PATCH 075/344] Implement CSRF protection --- apps/dav/lib/carddav/sharing/plugin.php | 24 ++++++++++++++++++++++++ apps/dav/lib/connector/sabre/auth.php | 2 +- apps/dav/lib/server.php | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/carddav/sharing/plugin.php b/apps/dav/lib/carddav/sharing/plugin.php index edc1a5fc117..eeb5abc6d23 100644 --- a/apps/dav/lib/carddav/sharing/plugin.php +++ b/apps/dav/lib/carddav/sharing/plugin.php @@ -2,6 +2,9 @@ namespace OCA\DAV\CardDAV\Sharing; +use OCA\DAV\Connector\Sabre\Auth; +use OCP\IRequest; +use Sabre\DAV\Exception\BadRequest; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; @@ -11,6 +14,11 @@ use Sabre\HTTP\ResponseInterface; class Plugin extends ServerPlugin { + public function __construct(Auth $authBackEnd, IRequest $request) { + $this->auth = $authBackEnd; + $this->request = $request; + } + /** * Reference to SabreDAV server object. * @@ -87,6 +95,9 @@ class Plugin extends ServerPlugin { return; } + // CSRF protection + $this->protectAgainstCSRF(); + $requestBody = $request->getBodyAsString(); // If this request handler could not deal with this POST request, it @@ -190,5 +201,18 @@ class Plugin extends ServerPlugin { } + private function protectAgainstCSRF() { + $user = $this->auth->getCurrentUser(); + if ($this->auth->isDavAuthenticated($user)) { + return true; + } + + if ($this->request->passesCSRFCheck()) { + return true; + } + + throw new BadRequest(); + } + } diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php index 39a7df31b7f..0394bfd6772 100644 --- a/apps/dav/lib/connector/sabre/auth.php +++ b/apps/dav/lib/connector/sabre/auth.php @@ -65,7 +65,7 @@ class Auth extends AbstractBasic { * @param string $username * @return bool */ - protected function isDavAuthenticated($username) { + public function isDavAuthenticated($username) { return !is_null($this->session->get(self::DAV_AUTHENTICATED)) && $this->session->get(self::DAV_AUTHENTICATED) === $username; } diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index 229f33858d9..44afcf23df6 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -50,6 +50,7 @@ class Server { $this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); + $this->server->addPlugin(new CardDAV\Sharing\Plugin($authBackend, \OC::$server->getRequest())); // addressbook plugins $this->server->addPlugin(new \Sabre\CardDAV\Plugin()); -- GitLab From bcc486ffdc4a61b9df665bc45660582ce227ac0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 18 Nov 2015 15:04:53 +0100 Subject: [PATCH 076/344] Adding an existing sharee is idempotent --- apps/dav/lib/carddav/carddavbackend.php | 32 ++++++++++++++----- .../tests/unit/carddav/carddavbackendtest.php | 8 +++-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index 3af70571610..348c166a531 100644 --- a/apps/dav/lib/carddav/carddavbackend.php +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -143,7 +143,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * - * Read the PropPatch documenation for more info and examples. + * Read the PropPatch documentation for more info and examples. * * @param string $addressBookId * @param \Sabre\DAV\PropPatch $propPatch @@ -623,6 +623,11 @@ class CardDavBackend implements BackendInterface, SyncSupport { return $cardData; } + /** + * @param string $path + * @param string[] $add + * @param string[] $remove + */ public function updateShares($path, $add, $remove) { foreach($add as $element) { $this->shareWith($path, $element); @@ -632,6 +637,10 @@ class CardDavBackend implements BackendInterface, SyncSupport { } } + /** + * @param string $addressBookUri + * @param string $element + */ private function shareWith($addressBookUri, $element) { $user = $element['href']; $parts = explode(':', $user, 2); @@ -643,11 +652,14 @@ class CardDavBackend implements BackendInterface, SyncSupport { return; } - $addressbook = $this->getAddressBooksByUri($addressBookUri); - if (is_null($addressbook)) { + $addressBook = $this->getAddressBooksByUri($addressBookUri); + if (is_null($addressBook)) { return; } + // remove the share if it already exists + $this->unshare($addressBookUri, $element); + $query = $this->db->getQueryBuilder(); $query->insert('dav_shares') ->values([ @@ -655,11 +667,15 @@ class CardDavBackend implements BackendInterface, SyncSupport { 'uri' => $query->createNamedParameter($addressBookUri), 'type' => $query->createNamedParameter('addressbook'), 'access' => $query->createNamedParameter(0), - 'resourceid' => $query->createNamedParameter($addressbook['id']) + 'resourceid' => $query->createNamedParameter($addressBook['id']) ]); $query->execute(); } + /** + * @param string $addressBookUri + * @param string $element + */ private function unshare($addressBookUri, $element) { $user = $element['href']; $parts = explode(':', $user, 2); @@ -671,14 +687,14 @@ class CardDavBackend implements BackendInterface, SyncSupport { return; } - $addressbook = $this->getAddressBooksByUri($addressBookUri); - if (is_null($addressbook)) { + $addressBook = $this->getAddressBooksByUri($addressBookUri); + if (is_null($addressBook)) { return; } $query = $this->db->getQueryBuilder(); $query->delete('dav_shares') - ->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressbook['id']))) + ->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBook['id']))) ->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook'))) ->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($parts[1]))) ; @@ -686,7 +702,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { } /** - * Returns the list of people whom this addressbook is shared with. + * Returns the list of people whom this address book is shared with. * * Every element in this array should have the following properties: * * href - Often a mailto: address diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php index d76db5a91e2..dd5e205242a 100644 --- a/apps/dav/tests/unit/carddav/carddavbackendtest.php +++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php @@ -204,6 +204,12 @@ class CardDavBackendTest extends TestCase { $shares = $this->backend->getShares('Example'); $this->assertEquals(1, count($shares)); + // adding the same sharee again has no effect + $this->backend->updateShares('Example', [['href' => 'principal:principals/best-friend']], []); + + $shares = $this->backend->getShares('Example'); + $this->assertEquals(1, count($shares)); + $books = $this->backend->getAddressBooksForUser('principals/best-friend'); $this->assertEquals(1, count($books)); @@ -214,7 +220,5 @@ class CardDavBackendTest extends TestCase { $books = $this->backend->getAddressBooksForUser('principals/best-friend'); $this->assertEquals(0, count($books)); - - } } -- GitLab From 02be8a3a12fbd63384f3dd79653ac94b05e646e6 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 13:32:05 +0100 Subject: [PATCH 077/344] Split getting cache entry and checking update to a seperate method --- lib/private/files/view.php | 104 ++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 58 deletions(-) diff --git a/lib/private/files/view.php b/lib/private/files/view.php index cee4b182425..2bac35cb18b 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1178,6 +1178,43 @@ class View { } } + /** + * @param \OC\Files\Storage\Storage $storage + * @param string $internalPath + * @param string $relativePath + * @return array|bool + */ + private function getCacheEntry($storage, $internalPath, $relativePath) { + $cache = $storage->getCache($internalPath); + $data = $cache->get($internalPath); + $watcher = $storage->getWatcher($internalPath); + + try { + // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data + if (!$data) { + $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); + if (!$storage->file_exists($internalPath)) { + $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); + return false; + } + $scanner = $storage->getScanner($internalPath); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + $data = $cache->get($internalPath); + $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); + } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) { + $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); + $watcher->update($internalPath, $data); + $this->updater->propagate($path); + $data = $cache->get($internalPath); + $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); + } + } catch (LockedException $e) { + // if the file is locked we just use the old cache info + } + + return $data; + } + /** * get the filesystem info * @@ -1204,46 +1241,15 @@ class View { $internalPath = $mount->getInternalPath($path); $data = null; if ($storage) { - $cache = $storage->getCache($internalPath); - - $data = $cache->get($internalPath); - $watcher = $storage->getWatcher($internalPath); - - try { - // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data - if (!$data) { - $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); - if (!$storage->file_exists($internalPath)) { - $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); - return false; - } - $scanner = $storage->getScanner($internalPath); - $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); - $data = $cache->get($internalPath); - $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); - } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) { - $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); - $watcher->update($internalPath, $data); - $this->updater->propagate($path); - $data = $cache->get($internalPath); - $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); - } - } catch (LockedException $e) { - // if the file is locked we just use the old cache info - } + $data = $this->getCacheEntry($storage, $internalPath, $relativePath); if ($data and isset($data['fileid'])) { - // upgrades from oc6 or lower might not have the permissions set in the file cache - if ($data['permissions'] === 0) { - $data['permissions'] = $storage->getPermissions($data['path']); - $cache->update($data['fileid'], array('permissions' => $data['permissions'])); - } if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mount points to the folder $extOnly = ($includeMountPoints === 'ext'); - $mountPoints = Filesystem::getMountPoints($path); - foreach ($mountPoints as $mountPoint) { - $subStorage = Filesystem::getStorage($mountPoint); + $mounts = Filesystem::getMountManager()->findIn($path); + foreach ($mounts as $mount) { + $subStorage = $mount->getStorage(); if ($subStorage) { // exclude shared storage ? if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) { @@ -1294,30 +1300,12 @@ class View { /** * @var \OC\Files\FileInfo[] $files */ - $files = array(); + $files = []; - $data = $cache->get($internalPath); - $watcher = $storage->getWatcher($internalPath); - try { - if (!$data or $data['size'] === -1) { - $this->lockFile($directory, ILockingProvider::LOCK_SHARED); - if (!$storage->file_exists($internalPath)) { - $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); - return array(); - } - $scanner = $storage->getScanner($internalPath); - $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); - $data = $cache->get($internalPath); - $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); - } else if ($watcher->needsUpdate($internalPath, $data)) { - $this->lockFile($directory, ILockingProvider::LOCK_SHARED); - $watcher->update($internalPath, $data); - $this->updater->propagate($path); - $data = $cache->get($internalPath); - $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); - } - } catch (LockedException $e) { - // if the file is locked we just use the old cache info + $data = $this->getCacheEntry($storage, $internalPath, $directory); + + if (!is_array($data) || !isset($data['fileid'])) { + return []; } $folderId = $data['fileid']; -- GitLab From 1736c70075c97aa4a10caf3c1a5790a11cce8675 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 13:52:02 +0100 Subject: [PATCH 078/344] Some more cleanup for getFIleInfo/getDirectoryContent --- lib/private/files/fileinfo.php | 11 ++++++ lib/private/files/view.php | 70 +++++++++++++++------------------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php index bb810dd45ed..2d2ef325d38 100644 --- a/lib/private/files/fileinfo.php +++ b/lib/private/files/fileinfo.php @@ -285,4 +285,15 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { public function getOwner() { return $this->owner; } + + /** + * Add a cache entry which is the child of this folder + * + * Sets the size, etag and size to for cross-storage childs + * + * @param array $data cache entry for the child + */ + public function addSubEntry($data) { + $this->data['size'] += isset($data['size']) ? $data['size'] : 0; + } } diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 2bac35cb18b..25bf7b547ca 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1226,9 +1226,8 @@ class View { */ public function getFileInfo($path, $includeMountPoints = true) { $this->assertPathLength($path); - $data = array(); if (!Filesystem::isValidPath($path)) { - return $data; + return false; } if (Cache\Scanner::isPartialFile($path)) { return $this->getPartFileInfo($path); @@ -1239,10 +1238,16 @@ class View { $mount = Filesystem::getMountManager()->find($path); $storage = $mount->getStorage(); $internalPath = $mount->getInternalPath($path); - $data = null; if ($storage) { $data = $this->getCacheEntry($storage, $internalPath, $relativePath); + if ($mount instanceof MoveableMount && $internalPath === '') { + $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE; + } + + $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath)); + $info = new FileInfo($path, $storage, $internalPath, $data, $mount, $owner); + if ($data and isset($data['fileid'])) { if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mount points to the folder @@ -1257,22 +1262,16 @@ class View { } $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); - $data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0; + $info->addSubEntry($rootEntry); } } } } - } - if (!$data) { - return false; - } - if ($mount instanceof MoveableMount && $internalPath === '') { - $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE; + return $info; } - $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath)); - return new FileInfo($path, $storage, $internalPath, $data, $mount, $owner); + return false; } /** @@ -1284,9 +1283,8 @@ class View { */ public function getDirectoryContent($directory, $mimetype_filter = '') { $this->assertPathLength($directory); - $result = array(); if (!Filesystem::isValidPath($directory)) { - return $result; + return []; } $path = $this->getAbsolutePath($directory); $path = Filesystem::normalizePath($path); @@ -1297,11 +1295,6 @@ class View { $cache = $storage->getCache($internalPath); $user = \OC_User::getUser(); - /** - * @var \OC\Files\FileInfo[] $files - */ - $files = []; - $data = $this->getCacheEntry($storage, $internalPath, $directory); if (!is_array($data) || !isset($data['fileid'])) { @@ -1311,18 +1304,16 @@ class View { $folderId = $data['fileid']; $contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter - foreach ($contents as $content) { - if ($content['permissions'] === 0) { - $content['permissions'] = $storage->getPermissions($content['path']); - $cache->update($content['fileid'], array('permissions' => $content['permissions'])); - } - // if sharing was disabled for the user we remove the share permissions + /** + * @var \OC\Files\FileInfo[] $files + */ + $files = array_map(function (array $content) use ($path, $storage, $mount) { if (\OCP\Util::isSharingDisabledForUser()) { $content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; } $owner = $this->getUserObjectForOwner($storage->getOwner($content['path'])); - $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner); - } + return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner); + }, $contents); //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders $mounts = Filesystem::getMountManager()->findIn($path); @@ -1333,7 +1324,8 @@ class View { if ($subStorage) { $subCache = $subStorage->getCache(''); - if ($subCache->getStatus('') === Cache\Cache::NOT_FOUND) { + $rootEntry = $subCache->get(''); + if (!$rootEntry) { $subScanner = $subStorage->getScanner(''); try { $subScanner->scanFile(''); @@ -1351,17 +1343,17 @@ class View { ); continue; } + $rootEntry = $subCache->get(''); } - $rootEntry = $subCache->get(''); if ($rootEntry) { $relativePath = trim(substr($mountPoint, $dirLength), '/'); if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder $entryName = substr($relativePath, 0, $pos); foreach ($files as &$entry) { - if ($entry['name'] === $entryName) { - $entry['size'] += $rootEntry['size']; + if ($entry->getName() === $entryName) { + $entry->addSubEntry($rootEntry); } } } else { //mountpoint in this folder, add an entry for it @@ -1398,23 +1390,23 @@ class View { } if ($mimetype_filter) { - foreach ($files as $file) { + $files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) { if (strpos($mimetype_filter, '/')) { - if ($file['mimetype'] === $mimetype_filter) { + if ($file->getMimetype() === $mimetype_filter) { $result[] = $file; } } else { - if ($file['mimepart'] === $mimetype_filter) { + if ($file->getMimePart() === $mimetype_filter) { $result[] = $file; } } - } - } else { - $result = $files; + }); } - } - return $result; + return $files; + } else { + return []; + } } /** -- GitLab From d5061b8139b4513c30aee782be94da7d69582710 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 14:34:38 +0100 Subject: [PATCH 079/344] fix fileinfo for non existing files --- lib/private/files/view.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 25bf7b547ca..70e8db83381 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1241,6 +1241,10 @@ class View { if ($storage) { $data = $this->getCacheEntry($storage, $internalPath, $relativePath); + if(!is_array($data)) { + return false; + } + if ($mount instanceof MoveableMount && $internalPath === '') { $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE; } -- GitLab From 02f847bc66ea9238c10a5a04d3980c81c7b09293 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 14:40:32 +0100 Subject: [PATCH 080/344] use relative path --- lib/private/files/view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 70e8db83381..0d5078fb3d8 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1204,7 +1204,7 @@ class View { } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) { $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); $watcher->update($internalPath, $data); - $this->updater->propagate($path); + $this->updater->propagate($relativePath); $data = $cache->get($internalPath); $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); } -- GitLab From d006a7c723e4c51a4132b0f8817392bf1f3cd534 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 14:48:19 +0100 Subject: [PATCH 081/344] Fix scanning of incomplete folders --- lib/private/files/view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 0d5078fb3d8..5f19558a4fc 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1191,7 +1191,7 @@ class View { try { // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data - if (!$data) { + if (!$data || $data['size'] === -1) { $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); if (!$storage->file_exists($internalPath)) { $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); -- GitLab From 888df3933df7f3588de11085035d2d3ae9292fb0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 16:14:08 +0100 Subject: [PATCH 082/344] take the etag of child mounts into account for the folder etag this replaces shared etag propagation --- apps/files_sharing/appinfo/app.php | 1 - apps/files_sharing/appinfo/application.php | 31 +--- apps/files_sharing/lib/mountprovider.php | 16 +- .../lib/propagation/changewatcher.php | 110 ----------- .../propagation/grouppropagationmanager.php | 133 -------------- .../lib/propagation/propagationmanager.php | 144 --------------- .../lib/propagation/recipientpropagator.php | 164 ----------------- apps/files_sharing/lib/sharedmount.php | 14 -- apps/files_sharing/lib/sharedpropagator.php | 43 +++++ apps/files_sharing/lib/sharedstorage.php | 16 +- .../tests/grouppropagationmanager.php | 173 ------------------ apps/files_sharing/tests/testcase.php | 1 - lib/private/files/cache/cache.php | 16 +- lib/private/files/cache/changepropagator.php | 24 ++- lib/private/files/cache/propagator.php | 66 +++++++ lib/private/files/fileinfo.php | 27 ++- lib/private/files/storage/common.php | 18 ++ lib/private/files/storage/storage.php | 8 + lib/private/files/storage/wrapper/wrapper.php | 7 + lib/private/files/view.php | 13 +- tests/lib/files/cache/changepropagator.php | 33 ++++ 21 files changed, 243 insertions(+), 815 deletions(-) delete mode 100644 apps/files_sharing/lib/propagation/changewatcher.php delete mode 100644 apps/files_sharing/lib/propagation/grouppropagationmanager.php delete mode 100644 apps/files_sharing/lib/propagation/propagationmanager.php delete mode 100644 apps/files_sharing/lib/propagation/recipientpropagator.php create mode 100644 apps/files_sharing/lib/sharedpropagator.php delete mode 100644 apps/files_sharing/tests/grouppropagationmanager.php create mode 100644 lib/private/files/cache/propagator.php diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 03e448be0af..5f56340d254 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -42,7 +42,6 @@ $l = \OC::$server->getL10N('files_sharing'); $application = new Application(); $application->registerMountProviders(); -$application->setupPropagation(); \OCP\App::registerAdmin('files_sharing', 'settings-admin'); \OCP\App::registerPersonal('files_sharing', 'settings-personal'); diff --git a/apps/files_sharing/appinfo/application.php b/apps/files_sharing/appinfo/application.php index 545a9425083..ffe3a6a513f 100644 --- a/apps/files_sharing/appinfo/application.php +++ b/apps/files_sharing/appinfo/application.php @@ -27,8 +27,6 @@ namespace OCA\Files_Sharing\AppInfo; use OCA\Files_Sharing\Helper; use OCA\Files_Sharing\MountProvider; -use OCA\Files_Sharing\Propagation\PropagationManager; -use OCA\Files_Sharing\Propagation\GroupPropagationManager; use OCP\AppFramework\App; use OC\AppFramework\Utility\SimpleContainer; use OCA\Files_Sharing\Controllers\ExternalSharesController; @@ -116,8 +114,7 @@ class Application extends App { /** @var \OCP\IServerContainer $server */ $server = $c->query('ServerContainer'); return new MountProvider( - $server->getConfig(), - $c->query('PropagationManager') + $server->getConfig() ); }); @@ -132,25 +129,6 @@ class Application extends App { ); }); - $container->registerService('PropagationManager', function (IContainer $c) { - /** @var \OCP\IServerContainer $server */ - $server = $c->query('ServerContainer'); - return new PropagationManager( - $server->getUserSession(), - $server->getConfig() - ); - }); - - $container->registerService('GroupPropagationManager', function (IContainer $c) { - /** @var \OCP\IServerContainer $server */ - $server = $c->query('ServerContainer'); - return new GroupPropagationManager( - $server->getUserSession(), - $server->getGroupManager(), - $c->query('PropagationManager') - ); - }); - /* * Register capabilities */ @@ -164,11 +142,4 @@ class Application extends App { $mountProviderCollection->registerProvider($this->getContainer()->query('MountProvider')); $mountProviderCollection->registerProvider($this->getContainer()->query('ExternalMountProvider')); } - - public function setupPropagation() { - $propagationManager = $this->getContainer()->query('PropagationManager'); - \OCP\Util::connectHook('OC_Filesystem', 'setup', $propagationManager, 'globalSetup'); - - $this->getContainer()->query('GroupPropagationManager')->globalSetup(); - } } diff --git a/apps/files_sharing/lib/mountprovider.php b/apps/files_sharing/lib/mountprovider.php index 458e7f2619b..74a2a3ff4d6 100644 --- a/apps/files_sharing/lib/mountprovider.php +++ b/apps/files_sharing/lib/mountprovider.php @@ -24,7 +24,6 @@ namespace OCA\Files_Sharing; use OC\Files\Filesystem; use OC\User\NoUserException; -use OCA\Files_Sharing\Propagation\PropagationManager; use OCP\Files\Config\IMountProvider; use OCP\Files\Storage\IStorageFactory; use OCP\IConfig; @@ -36,18 +35,11 @@ class MountProvider implements IMountProvider { */ protected $config; - /** - * @var \OCA\Files_Sharing\Propagation\PropagationManager - */ - protected $propagationManager; - /** * @param \OCP\IConfig $config - * @param \OCA\Files_Sharing\Propagation\PropagationManager $propagationManager */ - public function __construct(IConfig $config, PropagationManager $propagationManager) { + public function __construct(IConfig $config) { $this->config = $config; - $this->propagationManager = $propagationManager; } @@ -60,21 +52,15 @@ class MountProvider implements IMountProvider { */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = \OCP\Share::getItemsSharedWithUser('file', $user->getUID()); - $propagator = $this->propagationManager->getSharePropagator($user->getUID()); - $propagator->propagateDirtyMountPoints($shares); $shares = array_filter($shares, function ($share) { return $share['permissions'] > 0; }); $shares = array_map(function ($share) use ($user, $storageFactory) { - // for updating etags for the share owner when we make changes to this share. - $ownerPropagator = $this->propagationManager->getChangePropagator($share['uid_owner']); return new SharedMount( '\OC\Files\Storage\Shared', '/' . $user->getUID() . '/' . $share['file_target'], array( - 'propagationManager' => $this->propagationManager, - 'propagator' => $ownerPropagator, 'share' => $share, 'user' => $user->getUID() ), diff --git a/apps/files_sharing/lib/propagation/changewatcher.php b/apps/files_sharing/lib/propagation/changewatcher.php deleted file mode 100644 index e61c161da19..00000000000 --- a/apps/files_sharing/lib/propagation/changewatcher.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * @copyright Copyright (c) 2015, 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 OCA\Files_Sharing\Propagation; - -use OC\Files\Cache\ChangePropagator; -use OC\Files\Filesystem; -use OC\Files\View; -use OCA\Files_Sharing\SharedMount; - -/** - * Watch for changes made in a shared mount and propagate the changes to the share owner - */ -class ChangeWatcher { - /** - * The user view for the logged in user - * - * @var \OC\Files\View - */ - private $baseView; - - /** - * @var RecipientPropagator - */ - private $recipientPropagator; - - /** - * @param \OC\Files\View $baseView the view for the logged in user - * @param RecipientPropagator $recipientPropagator - */ - public function __construct(View $baseView, RecipientPropagator $recipientPropagator) { - $this->baseView = $baseView; - $this->recipientPropagator = $recipientPropagator; - } - - - public function writeHook($params) { - $path = $params['path']; - $fullPath = $this->baseView->getAbsolutePath($path); - $mount = $this->baseView->getMount($path); - if ($mount instanceof SharedMount) { - $this->propagateForOwner($mount->getShare(), $mount->getInternalPath($fullPath), $mount->getOwnerPropagator()); - } - $info = $this->baseView->getFileInfo($path); - if ($info) { - // trigger propagation if the subject of the write hook is shared. - // if a parent folder of $path is shared the propagation will be triggered from the change propagator hooks - $this->recipientPropagator->propagateById($info->getId()); - } - } - - public function renameHook($params) { - $path1 = $params['oldpath']; - $path2 = $params['newpath']; - $fullPath1 = $this->baseView->getAbsolutePath($path1); - $fullPath2 = $this->baseView->getAbsolutePath($path2); - $mount1 = $this->baseView->getMount($path1); - $mount2 = $this->baseView->getMount($path2); - if ($mount1 instanceof SharedMount and $mount1->getInternalPath($fullPath1) !== '') { - $this->propagateForOwner($mount1->getShare(), $mount1->getInternalPath($fullPath1), $mount1->getOwnerPropagator()); - } - if ($mount1 !== $mount2 and $mount2 instanceof SharedMount and $mount2->getInternalPath($fullPath2) !== '') { - $this->propagateForOwner($mount2->getShare(), $mount2->getInternalPath($fullPath2), $mount2->getOwnerPropagator()); - } - } - - /** - * @param array $share - * @param string $internalPath - * @param \OC\Files\Cache\ChangePropagator $propagator - */ - private function propagateForOwner($share, $internalPath, ChangePropagator $propagator) { - // note that we have already set up the filesystem for the owner when mounting the share - $view = new View('/' . $share['uid_owner'] . '/files'); - - $shareRootPath = $view->getPath($share['item_source']); - if (!is_null($shareRootPath)) { - $path = $shareRootPath . '/' . $internalPath; - $path = Filesystem::normalizePath($path); - $propagator->addChange($path); - $propagator->propagateChanges(); - } - } - - public function permissionsHook($params) { - $share = $params['share']; - - if ($share['item_type'] === 'file' || $share['item_type'] === 'folder') { - $this->recipientPropagator->markDirty($share, microtime(true)); - } - } -} diff --git a/apps/files_sharing/lib/propagation/grouppropagationmanager.php b/apps/files_sharing/lib/propagation/grouppropagationmanager.php deleted file mode 100644 index ba550dccec3..00000000000 --- a/apps/files_sharing/lib/propagation/grouppropagationmanager.php +++ /dev/null @@ -1,133 +0,0 @@ - - * - * @copyright Copyright (c) 2015, 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 OCA\Files_Sharing\Propagation; - -use OC\Files\Filesystem; -use OC\Files\View; -use OCP\IConfig; -use OCP\IUserSession; -use OCP\IGroup; -use OCP\IUser; -use OCP\IGroupManager; -use OCA\Files_Sharing\Propagation\PropagationManager; - -/** - * Propagate changes on group changes - */ -class GroupPropagationManager { - /** - * @var \OCP\IUserSession - */ - private $userSession; - - /** - * @var \OCP\IGroupManager - */ - private $groupManager; - - /** - * @var PropagationManager - */ - private $propagationManager; - - /** - * Items shared with a given user. - * Key is user id and value is an array of shares. - * - * @var array - */ - private $userShares = []; - - public function __construct(IUserSession $userSession, IGroupManager $groupManager, PropagationManager $propagationManager) { - $this->userSession = $userSession; - $this->groupManager = $groupManager; - $this->propagationManager = $propagationManager; - } - - public function onPreProcessUser(IGroup $group, IUser $targetUser) { - $this->userShares[$targetUser->getUID()] = $this->getUserShares($targetUser->getUID()); - } - - public function onPostAddUser(IGroup $group, IUser $targetUser) { - $targetUserId = $targetUser->getUID(); - $sharesAfter = $this->getUserShares($targetUserId); - - $this->propagateSharesDiff($targetUserId, $sharesAfter, $this->userShares[$targetUserId]); - unset($this->userShares[$targetUserId]); - } - - public function onPostRemoveUser(IGroup $group, IUser $targetUser) { - $targetUserId = $targetUser->getUID(); - $sharesAfter = $this->getUserShares($targetUserId); - - $this->propagateSharesDiff($targetUserId, $this->userShares[$targetUserId], $sharesAfter); - unset($this->userShares[$targetUserId]); - } - - private function getUserShares($targetUserId) { - return \OCP\Share::getItemsSharedWithUser('file', $targetUserId); - } - - /** - * Propagate etag for the shares that are in $shares1 but not in $shares2. - * - * @param string $targetUserId user id for which to propagate shares - * @param array $shares1 - * @param array $shares2 - */ - private function propagateSharesDiff($targetUserId, $shares1, $shares2) { - $sharesToPropagate = array_udiff( - $shares1, - $shares2, - function($share1, $share2) { - return ($share2['id'] - $share1['id']); - } - ); - - \OC\Files\Filesystem::initMountPoints($targetUserId); - $this->propagationManager->propagateSharesToUser($sharesToPropagate, $targetUserId); - } - - /** - * To be called from setupFS trough a hook - * - * Sets up listening to changes made to shares owned by the current user - */ - public function globalSetup() { - $user = $this->userSession->getUser(); - if (!$user) { - return; - } - - $this->groupManager->listen('\OC\Group', 'preAddUser', [$this, 'onPreProcessUser']); - $this->groupManager->listen('\OC\Group', 'postAddUser', [$this, 'onPostAddUser']); - $this->groupManager->listen('\OC\Group', 'preRemoveUser', [$this, 'onPreProcessUser']); - $this->groupManager->listen('\OC\Group', 'postRemoveUser', [$this, 'onPostRemoveUser']); - } - - public function tearDown() { - $this->groupManager->removeListener('\OC\Group', 'preAddUser', [$this, 'onPreProcessUser']); - $this->groupManager->removeListener('\OC\Group', 'postAddUser', [$this, 'onPostAddUser']); - $this->groupManager->removeListener('\OC\Group', 'preRemoveUser', [$this, 'onPreProcessUser']); - $this->groupManager->removeListener('\OC\Group', 'postRemoveUser', [$this, 'onPostRemoveUser']); - } -} diff --git a/apps/files_sharing/lib/propagation/propagationmanager.php b/apps/files_sharing/lib/propagation/propagationmanager.php deleted file mode 100644 index aac9428240d..00000000000 --- a/apps/files_sharing/lib/propagation/propagationmanager.php +++ /dev/null @@ -1,144 +0,0 @@ - - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 OCA\Files_Sharing\Propagation; - -use OC\Files\Filesystem; -use OC\Files\View; -use OCP\IConfig; -use OCP\IUserSession; -use OCP\Util; - - -/** - * Keep track of all change and share propagators by owner - */ -class PropagationManager { - /** - * @var \OCP\IUserSession - */ - private $userSession; - - /** - * @var \OCP\IConfig - */ - private $config; - - /** - * Change propagators for share owner - * - * @var \OC\Files\Cache\ChangePropagator[] - */ - private $changePropagators = []; - - /** - * Recipient propagators - * - * @var \OCA\Files_Sharing\Propagation\RecipientPropagator[] - */ - private $sharePropagators = []; - - public function __construct(IUserSession $userSession, IConfig $config) { - $this->userSession = $userSession; - $this->config = $config; - } - - /** - * @param string $user - * @return \OC\Files\Cache\ChangePropagator - */ - public function getChangePropagator($user) { - $activeUser = $this->userSession->getUser(); - - // for the local user we want to propagator from the active view, not any cached one - if ($activeUser && $activeUser->getUID() === $user && Filesystem::getView() instanceof View) { - // it's important that we take the existing propagator here to make sure we can listen to external changes - $this->changePropagators[$user] = Filesystem::getView()->getUpdater()->getPropagator(); - } - if (isset($this->changePropagators[$user])) { - return $this->changePropagators[$user]; - } - $view = new View('/' . $user . '/files'); - $this->changePropagators[$user] = $view->getUpdater()->getPropagator(); - return $this->changePropagators[$user]; - } - - /** - * Propagates etag changes for the given shares to the given user - * - * @param array array of shares for which to trigger etag change - * @param string $user - */ - public function propagateSharesToUser($shares, $user) { - $changePropagator = $this->getChangePropagator($user); - foreach ($shares as $share) { - $changePropagator->addChange($share['file_target']); - } - $time = microtime(true); - $changePropagator->propagateChanges(floor($time)); - } - - /** - * @param string $user - * @return \OCA\Files_Sharing\Propagation\RecipientPropagator - */ - public function getSharePropagator($user) { - if (isset($this->sharePropagators[$user])) { - return $this->sharePropagators[$user]; - } - $this->sharePropagators[$user] = new RecipientPropagator($user, $this->getChangePropagator($user), $this->config, $this); - return $this->sharePropagators[$user]; - } - - /** - * Attach the recipient propagator for $user to the change propagator of a share owner to mark shares as dirty when the owner makes a change to a share - * - * @param string $shareOwner - * @param string $user - */ - public function listenToOwnerChanges($shareOwner, $user) { - $sharePropagator = $this->getSharePropagator($user); - $ownerPropagator = $this->getChangePropagator($shareOwner); - $sharePropagator->attachToPropagator($ownerPropagator, $shareOwner); - } - - /** - * To be called from setupFS trough a hook - * - * Sets up listening to changes made to shares owned by the current user - */ - public function globalSetup() { - $user = $this->userSession->getUser(); - if (!$user) { - return; - } - $recipientPropagator = $this->getSharePropagator($user->getUID()); - $watcher = new ChangeWatcher(Filesystem::getView(), $recipientPropagator); - - // for marking shares owned by the active user as dirty when a file inside them changes - $this->listenToOwnerChanges($user->getUID(), $user->getUID()); - Util::connectHook('OC_Filesystem', 'post_write', $watcher, 'writeHook'); - Util::connectHook('OC_Filesystem', 'post_delete', $watcher, 'writeHook'); - Util::connectHook('OC_Filesystem', 'post_rename', $watcher, 'renameHook'); - Util::connectHook('OCP\Share', 'post_update_permissions', $watcher, 'permissionsHook'); - } -} diff --git a/apps/files_sharing/lib/propagation/recipientpropagator.php b/apps/files_sharing/lib/propagation/recipientpropagator.php deleted file mode 100644 index 5eacf4c0f6e..00000000000 --- a/apps/files_sharing/lib/propagation/recipientpropagator.php +++ /dev/null @@ -1,164 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2015, 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 OCA\Files_Sharing\Propagation; - -use OC\Files\Cache\ChangePropagator; -use OC\Files\View; -use OC\Share\Share; -use OCP\Files\NotFoundException; - -/** - * Propagate etags for share recipients - */ -class RecipientPropagator { - /** - * @var string - */ - protected $userId; - - /** - * @var \OC\Files\Cache\ChangePropagator - */ - protected $changePropagator; - - /** - * @var \OCP\IConfig - */ - protected $config; - - /** - * @var PropagationManager - */ - private $manager; - - /** - * @param string $userId current user, must match the propagator's - * user - * @param \OC\Files\Cache\ChangePropagator $changePropagator change propagator - * initialized with a view for $user - * @param \OCP\IConfig $config - * @param PropagationManager $manager - */ - public function __construct($userId, $changePropagator, $config, PropagationManager $manager) { - $this->userId = $userId; - $this->changePropagator = $changePropagator; - $this->config = $config; - $this->manager = $manager; - } - - /** - * Propagate the etag changes for all shares marked as dirty and mark the shares as clean - * - * @param array $shares the shares for the users - * @param int $time - */ - public function propagateDirtyMountPoints(array $shares, $time = null) { - if ($time === null) { - $time = microtime(true); - } - $dirtyShares = $this->getDirtyShares($shares); - foreach ($dirtyShares as $share) { - $this->changePropagator->addChange($share['file_target']); - } - if (count($dirtyShares)) { - $this->config->setUserValue($this->userId, 'files_sharing', 'last_propagate', $time); - $this->changePropagator->propagateChanges(floor($time)); - } - } - - /** - * Get all shares we need to update the etag for - * - * @param array $shares the shares for the users - * @return string[] - */ - protected function getDirtyShares($shares) { - $dirty = []; - $userTime = $this->config->getUserValue($this->userId, 'files_sharing', 'last_propagate', 0); - foreach ($shares as $share) { - $updateTime = $this->config->getAppValue('files_sharing', $share['id'], 0); - if ($updateTime >= $userTime) { - $dirty[] = $share; - } - } - return $dirty; - } - - /** - * @param array $share - * @param float $time - */ - public function markDirty($share, $time = null) { - if ($time === null) { - $time = microtime(true); - } - $this->config->setAppValue('files_sharing', $share['id'], $time); - } - - /** - * Listen on the propagator for updates made to shares owned by a user - * - * @param \OC\Files\Cache\ChangePropagator $propagator - * @param string $owner - */ - public function attachToPropagator(ChangePropagator $propagator, $owner) { - $propagator->listen('\OC\Files', 'propagate', function ($path, $entry) use ($owner) { - $this->propagateById($entry['fileid']); - }); - } - - protected $propagatingIds = []; - - /** - * @param int $id - */ - public function propagateById($id) { - if (isset($this->propagatingIds[$id])) { - return; - } - $this->propagatingIds[$id] = true; - $shares = Share::getAllSharesForFileId($id); - foreach ($shares as $share) { - // propagate down the share tree - $this->markDirty($share, microtime(true)); - - // propagate up the share tree - if ($share['share_with'] === $this->userId) { - $user = $share['uid_owner']; - $view = new View('/' . $user . '/files'); - - try { - $path = $view->getPath($share['file_source']); - } catch (NotFoundException $e) { - $path = null; - } - - $watcher = new ChangeWatcher($view, $this->manager->getSharePropagator($user)); - $watcher->writeHook(['path' => $path]); - } - } - - unset($this->propagatingIds[$id]); - } -} diff --git a/apps/files_sharing/lib/sharedmount.php b/apps/files_sharing/lib/sharedmount.php index a1387957867..275fea97c7f 100644 --- a/apps/files_sharing/lib/sharedmount.php +++ b/apps/files_sharing/lib/sharedmount.php @@ -38,11 +38,6 @@ class SharedMount extends MountPoint implements MoveableMount { */ protected $storage = null; - /** - * @var \OC\Files\Cache\ChangePropagator - */ - protected $ownerPropagator; - /** * @var \OC\Files\View */ @@ -54,8 +49,6 @@ class SharedMount extends MountPoint implements MoveableMount { private $user; public function __construct($storage, $mountpoint, $arguments = null, $loader = null) { - // first update the mount point before creating the parent - $this->ownerPropagator = $arguments['propagator']; $this->user = $arguments['user']; $this->recipientView = new View('/' . $this->user . '/files'); $newMountPoint = $this->verifyMountPoint($arguments['share']); @@ -201,11 +194,4 @@ class SharedMount extends MountPoint implements MoveableMount { public function getShare() { return $this->getStorage()->getShare(); } - - /** - * @return \OC\Files\Cache\ChangePropagator - */ - public function getOwnerPropagator() { - return $this->ownerPropagator; - } } diff --git a/apps/files_sharing/lib/sharedpropagator.php b/apps/files_sharing/lib/sharedpropagator.php new file mode 100644 index 00000000000..fcb4b92dd33 --- /dev/null +++ b/apps/files_sharing/lib/sharedpropagator.php @@ -0,0 +1,43 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Files_Sharing; + +use OC\Files\Cache\Propagator; + +class SharedPropagator extends Propagator { + /** + * @var \OC\Files\Storage\Shared + */ + protected $storage; + + /** + * @param string $internalPath + * @param int $time + * @return array[] all propagated entries + */ + public function propagateChange($internalPath, $time) { + $source = $this->storage->getSourcePath($internalPath); + /** @var \OC\Files\Storage\Storage $storage */ + list($storage, $sourceInternalPath) = \OC\Files\Filesystem::resolvePath($source); + return $storage->getPropagator()->propagateChange($sourceInternalPath, $time); + } +} diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 18e02844179..4807b5ee738 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -50,11 +50,6 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage { */ private $ownerView; - /** - * @var \OCA\Files_Sharing\Propagation\PropagationManager - */ - private $propagationManager; - /** * @var string */ @@ -65,7 +60,6 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage { public function __construct($arguments) { $this->share = $arguments['share']; $this->ownerView = $arguments['ownerView']; - $this->propagationManager = $arguments['propagationManager']; $this->user = $arguments['user']; } @@ -75,9 +69,6 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage { } $this->initialized = true; Filesystem::initMountPoints($this->share['uid_owner']); - - // for updating our etags when changes are made to the share from the owners side (probably indirectly by us trough another share) - $this->propagationManager->listenToOwnerChanges($this->share['uid_owner'], $this->user); } /** @@ -571,6 +562,13 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage { return new \OC\Files\Cache\Shared_Watcher($storage); } + public function getPropagator($storage = null) { + if (!$storage) { + $storage = $this; + } + return new \OCA\Files_Sharing\SharedPropagator($storage); + } + public function getOwner($path) { if ($path == '') { $path = $this->getMountPoint(); diff --git a/apps/files_sharing/tests/grouppropagationmanager.php b/apps/files_sharing/tests/grouppropagationmanager.php deleted file mode 100644 index ea32ca4f7ec..00000000000 --- a/apps/files_sharing/tests/grouppropagationmanager.php +++ /dev/null @@ -1,173 +0,0 @@ - - * - * @copyright Copyright (c) 2015, 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 OCA\Files_sharing\Tests; - -use OC\Files\View; -use OCP\IGroupManager; -use OCP\IGroup; -use OCP\IUser; -use OCP\Share; -use OCA\Files_Sharing\Propagation\GroupPropagationManager; -use OCA\Files_Sharing\Propagation\PropagationManager; - -class GroupPropagationManagerTest extends TestCase { - - /** - * @var GroupPropagationManager - */ - private $groupPropagationManager; - - /** - * @var IGroupManager - */ - private $groupManager; - - /** - * @var PropagationManager - */ - private $propagationManager; - - /** - * @var IGroup - */ - private $recipientGroup; - - /** - * @var IUser - */ - private $recipientUser; - - /** - * @var array - */ - private $fileInfo; - - protected function setUp() { - parent::setUp(); - - $user = $this->getMockBuilder('\OCP\IUser') - ->disableOriginalConstructor() - ->getMock(); - $user->method('getUID')->willReturn(self::TEST_FILES_SHARING_API_USER1); - $userSession = $this->getMockBuilder('\OCP\IUserSession') - ->disableOriginalConstructor() - ->getMock(); - $userSession->method('getUser')->willReturn(selF::TEST_FILES_SHARING_API_USER1); - - $this->propagationManager = $this->getMockBuilder('OCA\Files_Sharing\Propagation\PropagationManager') - ->disableOriginalConstructor() - ->getMock(); - - $this->groupManager = \OC::$server->getGroupManager(); - $this->groupPropagationManager = new GroupPropagationManager( - $userSession, - $this->groupManager, - $this->propagationManager - ); - $this->groupPropagationManager->globalSetup(); - - // since the sharing code is not mockable, we have to create a real folder - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); - $view1->mkdir('/folder'); - - $this->fileInfo = $view1->getFileInfo('/folder'); - - $this->recipientGroup = $this->groupManager->get(self::TEST_FILES_SHARING_API_GROUP1); - $this->recipientUser = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER3); - - Share::shareItem( - 'folder', - $this->fileInfo['fileid'], - Share::SHARE_TYPE_GROUP, - $this->recipientGroup->getGID(), - \OCP\Constants::PERMISSION_READ - ); - - $this->loginAsUser($this->recipientUser->getUID()); - } - - protected function tearDown() { - $this->groupPropagationManager->tearDown(); - $this->recipientGroup->removeUser($this->recipientUser); - parent::tearDown(); - } - - public function testPropagateWhenAddedToGroup() { - $this->propagationManager->expects($this->once()) - ->method('propagateSharesToUser') - ->with($this->callback(function($shares) { - if (count($shares) !== 1) { - return false; - } - $share = array_values($shares)[0]; - return $share['file_source'] === $this->fileInfo['fileid'] && - $share['share_with'] === $this->recipientGroup->getGID() && - $share['file_target'] === '/folder'; - }), $this->recipientUser->getUID()); - - $this->recipientGroup->addUser($this->recipientUser); - } - - public function testPropagateWhenRemovedFromGroup() { - $this->recipientGroup->addUser($this->recipientUser); - - $this->propagationManager->expects($this->once()) - ->method('propagateSharesToUser') - ->with($this->callback(function($shares) { - if (count($shares) !== 1) { - return false; - } - $share = array_values($shares)[0]; - return $share['file_source'] === $this->fileInfo['fileid'] && - $share['share_with'] === $this->recipientGroup->getGID() && - $share['file_target'] === '/folder'; - }), $this->recipientUser->getUID()); - - $this->recipientGroup->removeUser($this->recipientUser); - } - - public function testPropagateWhenRemovedFromGroupWithSubdirTarget() { - $this->recipientGroup->addUser($this->recipientUser); - - // relogin to refresh mount points - $this->loginAsUser($this->recipientUser->getUID()); - $recipientView = new View('/' . $this->recipientUser->getUID() . '/files'); - - $this->assertTrue($recipientView->mkdir('sub')); - $this->assertTrue($recipientView->rename('folder', 'sub/folder')); - - $this->propagationManager->expects($this->once()) - ->method('propagateSharesToUser') - ->with($this->callback(function($shares) { - if (count($shares) !== 1) { - return false; - } - $share = array_values($shares)[0]; - return $share['file_source'] === $this->fileInfo['fileid'] && - $share['share_with'] === $this->recipientGroup->getGID() && - $share['file_target'] === '/sub/folder'; - }), $this->recipientUser->getUID()); - - $this->recipientGroup->removeUser($this->recipientUser); - } -} diff --git a/apps/files_sharing/tests/testcase.php b/apps/files_sharing/tests/testcase.php index c91734a5b03..6a72a34149a 100644 --- a/apps/files_sharing/tests/testcase.php +++ b/apps/files_sharing/tests/testcase.php @@ -61,7 +61,6 @@ abstract class TestCase extends \Test\TestCase { $application = new Application(); $application->registerMountProviders(); - $application->setupPropagation(); // reset backend \OC_User::clearBackends(); diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 40477243324..e6110c1925d 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -160,6 +160,7 @@ class Cache { } else { //fix types $data['fileid'] = (int)$data['fileid']; + $data['parent'] = (int)$data['parent']; $data['size'] = 0 + $data['size']; $data['mtime'] = (int)$data['mtime']; $data['storage_mtime'] = (int)$data['storage_mtime']; @@ -391,12 +392,17 @@ class Cache { if ($file === '') { return -1; } else { - $parent = dirname($file); - if ($parent === '.') { - $parent = ''; - } - return $this->getId($parent); + $parent = $this->getParentPath($file); + return (int) $this->getId($parent); + } + } + + private function getParentPath($path) { + $parent = dirname($path); + if ($parent === '.') { + $parent = ''; } + return $parent; } /** diff --git a/lib/private/files/cache/changepropagator.php b/lib/private/files/cache/changepropagator.php index 9696a82257e..2a48eb13c59 100644 --- a/lib/private/files/cache/changepropagator.php +++ b/lib/private/files/cache/changepropagator.php @@ -22,6 +22,7 @@ namespace OC\Files\Cache; +use OC\Files\Filesystem; use OC\Hooks\BasicEmitter; /** @@ -61,23 +62,30 @@ class ChangePropagator extends BasicEmitter { * @param int $time (optional) the mtime to set for the folders, if not set the current time is used */ public function propagateChanges($time = null) { - $parents = $this->getAllParents(); - $this->changedFiles = array(); + $changes = $this->getChanges(); + $this->changedFiles = []; if (!$time) { $time = time(); } - foreach ($parents as $parent) { + foreach ($changes as $change) { /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = $this->view->resolvePath($parent); + $absolutePath = $this->view->getAbsolutePath($change); + $mount = $this->view->getMount($change); + $storage = $mount->getStorage(); + $internalPath = $mount->getInternalPath($absolutePath); if ($storage) { - $cache = $storage->getCache(); - $entry = $cache->get($internalPath); - $cache->update($entry['fileid'], array('mtime' => max($time, $entry['mtime']), 'etag' => $storage->getETag($internalPath))); - $this->emit('\OC\Files', 'propagate', [$parent, $entry]); + $propagator = $storage->getPropagator(); + $propagatedEntries = $propagator->propagateChange($internalPath, $time); + + foreach ($propagatedEntries as $entry) { + $absolutePath = Filesystem::normalizePath($mount->getMountPoint() . '/' . $entry['path']); + $relativePath = $this->view->getRelativePath($absolutePath); + $this->emit('\OC\Files', 'propagate', [$relativePath, $entry]); + } } } } diff --git a/lib/private/files/cache/propagator.php b/lib/private/files/cache/propagator.php new file mode 100644 index 00000000000..bd11cef5990 --- /dev/null +++ b/lib/private/files/cache/propagator.php @@ -0,0 +1,66 @@ + + * + * @copyright Copyright (c) 2015, 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\Files\Cache; + +/** + * Propagate etags and mtimes within the storage + */ +class Propagator { + /** + * @var \OC\Files\Storage\Storage + */ + protected $storage; + + /** + * @param \OC\Files\Storage\Storage $storage + */ + public function __construct(\OC\Files\Storage\Storage $storage) { + $this->storage = $storage; + } + + + /** + * @param string $internalPath + * @param int $time + * @return array[] all propagated entries + */ + public function propagateChange($internalPath, $time) { + $cache = $this->storage->getCache($internalPath); + + $parentId = $cache->getParentId($internalPath); + $propagatedEntries = []; + while ($parentId !== -1) { + $entry = $cache->get($parentId); + $propagatedEntries[] = $entry; + if (!$entry) { + return $propagatedEntries; + } + $mtime = max($time, $entry['mtime']); + + $cache->update($parentId, ['mtime' => $mtime, 'etag' => $this->storage->getETag($entry['path'])]); + + $parentId = $entry['parent']; + } + + return $propagatedEntries; + } +} diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php index 2d2ef325d38..5b5e8697004 100644 --- a/lib/private/files/fileinfo.php +++ b/lib/private/files/fileinfo.php @@ -61,6 +61,11 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { */ private $owner; + /** + * @var string[] + */ + private $childEtags = []; + /** * @param string|boolean $path * @param Storage\Storage $storage @@ -93,6 +98,8 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { public function offsetGet($offset) { if ($offset === 'type') { return $this->getType(); + } else if ($offset === 'etag') { + return $this->getEtag(); } elseif (isset($this->data[$offset])) { return $this->data[$offset]; } else { @@ -153,7 +160,12 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { * @return string */ public function getEtag() { - return $this->data['etag']; + if (count($this->childEtags) > 0) { + $combinedEtag = $this->data['etag'] . '::' . implode('::', $this->childEtags); + return md5($combinedEtag); + } else { + return $this->data['etag']; + } } /** @@ -292,8 +304,19 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { * Sets the size, etag and size to for cross-storage childs * * @param array $data cache entry for the child + * @param string $entryPath full path of the child entry */ - public function addSubEntry($data) { + public function addSubEntry($data, $entryPath) { $this->data['size'] += isset($data['size']) ? $data['size'] : 0; + if (isset($data['mtime'])) { + $this->data['mtime'] = max($this->data['mtime'], $data['mtime']); + } + if (isset($data['etag'])) { + // prefix the etag with the relative path of the subentry to propagate etag on mount moves + $relativeEntryPath = substr($entryPath, strlen($this->getPath())); + // attach the permissions to propagate etag on permision changes of submounts + $permissions = isset($data['permissions']) ? $data['permissions'] : 0; + $this->childEtags[] = $relativeEntryPath . '/' . $data['etag'] . $permissions; + } } } diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index 77a70226b37..a52e7c35f87 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -37,6 +37,7 @@ namespace OC\Files\Storage; use OC\Files\Cache\Cache; +use OC\Files\Cache\Propagator; use OC\Files\Cache\Scanner; use OC\Files\Filesystem; use OC\Files\Cache\Watcher; @@ -64,6 +65,7 @@ abstract class Common implements Storage { protected $cache; protected $scanner; protected $watcher; + protected $propagator; protected $storageCache; protected $mountOptions = []; @@ -345,6 +347,22 @@ abstract class Common implements Storage { return $this->watcher; } + /** + * get a propagator instance for the cache + * + * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher + * @return \OC\Files\Cache\Propagator + */ + public function getPropagator($storage = null) { + if (!$storage) { + $storage = $this; + } + if (!isset($this->propagator)) { + $this->propagator = new Propagator($storage); + } + return $this->propagator; + } + public function getStorageCache($storage = null) { if (!$storage) { $storage = $this; diff --git a/lib/private/files/storage/storage.php b/lib/private/files/storage/storage.php index f46ac544b56..3399c717890 100644 --- a/lib/private/files/storage/storage.php +++ b/lib/private/files/storage/storage.php @@ -67,6 +67,14 @@ interface Storage extends \OCP\Files\Storage { */ public function getWatcher($path = '', $storage = null); + /** + * get a propagator instance for the cache + * + * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher + * @return \OC\Files\Cache\Propagator + */ + public function getPropagator($storage = null); + /** * @return \OC\Files\Cache\Storage */ diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php index 048738170db..5327b94211b 100644 --- a/lib/private/files/storage/wrapper/wrapper.php +++ b/lib/private/files/storage/wrapper/wrapper.php @@ -430,6 +430,13 @@ class Wrapper implements \OC\Files\Storage\Storage { return $this->storage->getWatcher($path, $storage); } + public function getPropagator($storage = null) { + if (!$storage) { + $storage = $this; + } + return $this->storage->getPropagator($storage); + } + /** * @return \OC\Files\Cache\Storage */ diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 5f19558a4fc..3ad9d36a384 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -707,10 +707,6 @@ class View { } else if ($result) { if ($internalPath1 !== '') { // dont do a cache update for moved mounts $this->updater->rename($path1, $path2); - } else { // only do etag propagation - $this->getUpdater()->getPropagator()->addChange($path1); - $this->getUpdater()->getPropagator()->addChange($path2); - $this->getUpdater()->getPropagator()->propagateChanges(); } } @@ -1179,6 +1175,11 @@ class View { } /** + * Get file info from cache + * + * If the file is not in cached it will be scanned + * If the file has changed on storage the cache will be updated + * * @param \OC\Files\Storage\Storage $storage * @param string $internalPath * @param string $relativePath @@ -1266,7 +1267,7 @@ class View { } $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); - $info->addSubEntry($rootEntry); + $info->addSubEntry($rootEntry, $mount->getMountPoint()); } } } @@ -1357,7 +1358,7 @@ class View { $entryName = substr($relativePath, 0, $pos); foreach ($files as &$entry) { if ($entry->getName() === $entryName) { - $entry->addSubEntry($rootEntry); + $entry->addSubEntry($rootEntry, $mountPoint); } } } else { //mountpoint in this folder, add an entry for it diff --git a/tests/lib/files/cache/changepropagator.php b/tests/lib/files/cache/changepropagator.php index 1b56da5e97c..9108330eb9b 100644 --- a/tests/lib/files/cache/changepropagator.php +++ b/tests/lib/files/cache/changepropagator.php @@ -94,4 +94,37 @@ class ChangePropagator extends \Test\TestCase { $this->assertEquals(100, $time - $cache->get('foo')['mtime']); $this->assertEquals(100, $time - $cache->get('foo/bar')['mtime']); } + + public function testPropagateCrossStorage() { + $storage = new Temporary(); + $this->view->mkdir('/foo'); + Filesystem::mount($storage, [], $this->view->getAbsolutePath('/foo/submount')); + $this->view->mkdir('/foo/submount/bar'); + $this->view->file_put_contents('/foo/submount/bar/sad.txt', 'qwerty'); + + $oldInfo1 = $this->view->getFileInfo('/'); + $oldInfo2 = $this->view->getFileInfo('/foo'); + $oldInfo3 = $this->view->getFileInfo('/foo/submount'); + $oldInfo4 = $this->view->getFileInfo('/foo/submount/bar'); + + $time = time() + 50; + + $this->propagator->addChange('/foo/submount/bar/sad.txt'); + $this->propagator->propagateChanges($time); + + $newInfo1 = $this->view->getFileInfo('/'); + $newInfo2 = $this->view->getFileInfo('/foo'); + $newInfo3 = $this->view->getFileInfo('/foo/submount'); + $newInfo4 = $this->view->getFileInfo('/foo/submount/bar'); + + $this->assertEquals($newInfo1->getMTime(), $time); + $this->assertEquals($newInfo2->getMTime(), $time); + $this->assertEquals($newInfo3->getMTime(), $time); + $this->assertEquals($newInfo4->getMTime(), $time); + + $this->assertNotSame($oldInfo1->getEtag(), $newInfo1->getEtag()); + $this->assertNotSame($oldInfo2->getEtag(), $newInfo2->getEtag()); + $this->assertNotSame($oldInfo3->getEtag(), $newInfo3->getEtag()); + $this->assertNotSame($oldInfo4->getEtag(), $newInfo3->getEtag()); + } } -- GitLab From a95d4c2b22e2cf0deb4958bc3aa3b20ed9d0463c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 10 Nov 2015 16:31:30 +0100 Subject: [PATCH 083/344] update tests --- apps/files_sharing/tests/etagpropagation.php | 3 +- apps/files_trashbin/tests/trashbin.php | 1 - apps/files_versions/tests/versions.php | 1 - tests/lib/files/cache/updaterlegacy.php | 47 +++++--------------- tests/lib/files/etagtest.php | 1 - 5 files changed, 12 insertions(+), 41 deletions(-) diff --git a/apps/files_sharing/tests/etagpropagation.php b/apps/files_sharing/tests/etagpropagation.php index 1abf04df84f..2a33732d63f 100644 --- a/apps/files_sharing/tests/etagpropagation.php +++ b/apps/files_sharing/tests/etagpropagation.php @@ -193,7 +193,8 @@ class EtagPropagation extends TestCase { public function testOwnerWritesToSingleFileShare() { $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::file_put_contents('/foo.txt', 'bar'); + Filesystem::file_put_contents('/foo.txt', 'longer_bar'); + Filesystem::touch('/foo.txt', time() - 1); $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4, self::TEST_FILES_SHARING_API_USER3]); $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2]); diff --git a/apps/files_trashbin/tests/trashbin.php b/apps/files_trashbin/tests/trashbin.php index e28b854ca1f..934f831ef74 100644 --- a/apps/files_trashbin/tests/trashbin.php +++ b/apps/files_trashbin/tests/trashbin.php @@ -65,7 +65,6 @@ class Test_Trashbin extends \Test\TestCase { \OC::registerShareHooks(); $application = new \OCA\Files_Sharing\AppInfo\Application(); $application->registerMountProviders(); - $application->setupPropagation(); //disable encryption \OC_App::disable('encryption'); diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php index b9bc0932a84..6ebbf830e70 100644 --- a/apps/files_versions/tests/versions.php +++ b/apps/files_versions/tests/versions.php @@ -51,7 +51,6 @@ class Test_Files_Versioning extends \Test\TestCase { $application = new \OCA\Files_Sharing\AppInfo\Application(); $application->registerMountProviders(); - $application->setupPropagation(); // create test user self::loginHelper(self::TEST_VERSIONS_USER2, true); diff --git a/tests/lib/files/cache/updaterlegacy.php b/tests/lib/files/cache/updaterlegacy.php index f4d52e9a390..c1a0d3d8230 100644 --- a/tests/lib/files/cache/updaterlegacy.php +++ b/tests/lib/files/cache/updaterlegacy.php @@ -10,6 +10,7 @@ namespace Test\Files\Cache; use \OC\Files\Filesystem as Filesystem; use OC\Files\Storage\Temporary; +use OC\Files\View; class UpdaterLegacy extends \Test\TestCase { /** @@ -111,7 +112,8 @@ class UpdaterLegacy extends \Test\TestCase { $storage2->getScanner()->scan(''); //initialize etags $cache2 = $storage2->getCache(); Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); - $folderCachedData = $this->cache->get('folder'); + $view = new View('/' . self::$user . '/files'); + $folderCachedData = $view->getFileInfo('folder'); $substorageCachedData = $cache2->get(''); Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); $this->assertTrue($cache2->inCache('foo.txt')); @@ -124,7 +126,7 @@ class UpdaterLegacy extends \Test\TestCase { $this->assertInternalType('string', $cachedData['etag']); $this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']); - $cachedData = $this->cache->get('folder'); + $cachedData = $view->getFileInfo('folder'); $this->assertInternalType('string', $folderCachedData['etag']); $this->assertInternalType('string', $cachedData['etag']); $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); @@ -168,8 +170,9 @@ class UpdaterLegacy extends \Test\TestCase { $cache2 = $storage2->getCache(); Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); + $view = new View('/' . self::$user . '/files'); $this->assertTrue($cache2->inCache('foo.txt')); - $folderCachedData = $this->cache->get('folder'); + $folderCachedData = $view->getFileInfo('folder'); $substorageCachedData = $cache2->get(''); Filesystem::unlink('folder/substorage/foo.txt'); $this->assertFalse($cache2->inCache('foo.txt')); @@ -180,7 +183,7 @@ class UpdaterLegacy extends \Test\TestCase { $this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']); $this->assertGreaterThanOrEqual($substorageCachedData['mtime'], $cachedData['mtime']); - $cachedData = $this->cache->get('folder'); + $cachedData = $view->getFileInfo('folder'); $this->assertInternalType('string', $folderCachedData['etag']); $this->assertInternalType('string', $cachedData['etag']); $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); @@ -222,8 +225,9 @@ class UpdaterLegacy extends \Test\TestCase { $cache2 = $storage2->getCache(); Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); + $view = new View('/' . self::$user . '/files'); $this->assertTrue($cache2->inCache('foo.txt')); - $folderCachedData = $this->cache->get('folder'); + $folderCachedData = $view->getFileInfo('folder'); $substorageCachedData = $cache2->get(''); $fooCachedData = $cache2->get('foo.txt'); Filesystem::rename('folder/substorage/foo.txt', 'folder/substorage/bar.txt'); @@ -240,7 +244,7 @@ class UpdaterLegacy extends \Test\TestCase { // rename can cause mtime change - invalid assert // $this->assertEquals($mtime, $cachedData['mtime']); - $cachedData = $this->cache->get('folder'); + $cachedData = $view->getFileInfo('folder'); $this->assertInternalType('string', $folderCachedData['etag']); $this->assertInternalType('string', $cachedData['etag']); $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); @@ -287,35 +291,4 @@ class UpdaterLegacy extends \Test\TestCase { $this->assertEquals($time, $cachedData['mtime']); } - public function testTouchWithMountPoints() { - $storage2 = new \OC\Files\Storage\Temporary(array()); - $cache2 = $storage2->getCache(); - Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); - Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); - $this->assertTrue($cache2->inCache('foo.txt')); - $folderCachedData = $this->cache->get('folder'); - $substorageCachedData = $cache2->get(''); - $fooCachedData = $cache2->get('foo.txt'); - $cachedData = $cache2->get('foo.txt'); - $time = 1371006070; - $this->cache->put('folder', ['mtime' => $time - 100]); - Filesystem::touch('folder/substorage/foo.txt', $time); - $cachedData = $cache2->get('foo.txt'); - $this->assertInternalType('string', $fooCachedData['etag']); - $this->assertInternalType('string', $cachedData['etag']); - $this->assertNotSame($fooCachedData['etag'], $cachedData['etag']); - $this->assertEquals($time, $cachedData['mtime']); - - $cachedData = $cache2->get(''); - $this->assertInternalType('string', $substorageCachedData['etag']); - $this->assertInternalType('string', $cachedData['etag']); - $this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']); - - $cachedData = $this->cache->get('folder'); - $this->assertInternalType('string', $folderCachedData['etag']); - $this->assertInternalType('string', $cachedData['etag']); - $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); - $this->assertEquals($time, $cachedData['mtime']); - } - } diff --git a/tests/lib/files/etagtest.php b/tests/lib/files/etagtest.php index 1a11b29cf00..192768d04af 100644 --- a/tests/lib/files/etagtest.php +++ b/tests/lib/files/etagtest.php @@ -27,7 +27,6 @@ class EtagTest extends \Test\TestCase { \OC_Hook::clear('OC_Filesystem', 'setup'); $application = new \OCA\Files_Sharing\AppInfo\Application(); $application->registerMountProviders(); - $application->setupPropagation(); \OCP\Share::registerBackend('file', 'OC_Share_Backend_File'); \OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file'); -- GitLab From a990e0ac1d5a50618ed976e3354e47e443277de9 Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Wed, 18 Nov 2015 11:09:34 +0000 Subject: [PATCH 084/344] Added some requirements for first test case --- .../features/bootstrap/FeatureContext.php | 108 ++++++++++++++++-- build/integration/features/sharing-v1.feature | 30 +++++ .../features/webdav-related.feature | 20 ++++ 3 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 build/integration/features/webdav-related.feature diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 3d579f52810..7176a19064a 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -238,8 +238,23 @@ class FeatureContext implements Context, SnippetAcceptingContext { } /** - * @Given /^user "([^"]*)" belongs to group "([^"]*)"$/ + * @Then /^check that user "([^"]*)" belongs to group "([^"]*)"$/ */ + public function checkThatUserBelongsToGroup($user, $group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user/groups"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfGroupsResponded($this->response); + sort($respondedArray); + PHPUnit_Framework_Assert::assertContains($group, $respondedArray); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + public function userBelongsToGroup($user, $group) { $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user/groups"; $client = new Client(); @@ -251,8 +266,26 @@ class FeatureContext implements Context, SnippetAcceptingContext { $this->response = $client->get($fullUrl, $options); $groups = array($group); $respondedArray = $this->getArrayOfGroupsResponded($this->response); - PHPUnit_Framework_Assert::assertEquals($groups, $respondedArray, "", 0.0, 10, true); - PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + + if (array_key_exists($group, $respondedArray)) { + return True; + } else{ + return False; + } + } + + /** + * @Given /^user "([^"]*)" belongs to group "([^"]*)"$/ + */ + public function assureUserBelongsToGroup($user, $group){ + if (!$this->userBelongsToGroup($user, $group)){ + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->addingUserToGroup($user, $group); + $this->currentUser = $previous_user; + } + $this->checkThatUserBelongsToGroup($user, $group); + } /** @@ -818,10 +851,10 @@ class FeatureContext implements Context, SnippetAcceptingContext { PHPUnit_Framework_Assert::assertEquals(False, $this->isFieldInResponse('share_with', "$user")); } - public function isUserInSharedData($user){ + public function isUserOrGroupInSharedData($userOrGroup){ $data = $this->response->xml()->data[0]; foreach($data as $element) { - if ($element->share_with == $user){ + if ($element->share_with == $userOrGroup){ return True; } } @@ -841,13 +874,70 @@ class FeatureContext implements Context, SnippetAcceptingContext { $options['auth'] = [$user1, $this->regularUser]; } $this->response = $client->get($fullUrl, $options); - if ($this->isUserInSharedData($user2)){ + if ($this->isUserOrGroupInSharedData($user2)){ return; } else { $this->createShare($user1, $filepath, 0, $user2, null, null, null); } $this->response = $client->get($fullUrl, $options); - PHPUnit_Framework_Assert::assertEquals(True, $this->isUserInSharedData($user2)); + PHPUnit_Framework_Assert::assertEquals(True, $this->isUserOrGroupInSharedData($user2)); + } + + /** + * @Given /^file "([^"]*)" from user "([^"]*)" is shared with group "([^"]*)"$/ + */ + public function assureFileIsSharedWithGroup($filepath, $user, $group){ + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares" . "?path=$filepath"; + $client = new Client(); + $options = []; + if ($user === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$user, $this->regularUser]; + } + $this->response = $client->get($fullUrl, $options); + if ($this->isUserOrGroupInSharedData($group)){ + return; + } else { + $this->createShare($user, $filepath, 1, $group, null, null, null); + } + $this->response = $client->get($fullUrl, $options); + PHPUnit_Framework_Assert::assertEquals(True, $this->isUserOrGroupInSharedData($group)); + } + + public function makeDavRequest($user, $method, $path, $headers){ + $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav" . "$path"; + $client = new Client(); + $options = []; + if ($user === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$user, $this->regularUser]; + } + $request = $client->createRequest($method, $fullUrl, $options); + foreach ($headers as $key => $value) { + $request->addHeader($key, $value); + } + $this->response = $client->send($request); + } + + /** + * @Given /^User "([^"]*)" moved file "([^"]*)" to "([^"]*)"$/ + */ + public function userMovedFile($user, $fileSource, $fileDestination){ + $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav"; + $headers['Destination'] = $fullUrl . $fileDestination; + $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + PHPUnit_Framework_Assert::assertEquals(201, $this->response->getStatusCode()); + } + + /** + * @When /^User "([^"]*)" moves file "([^"]*)" to "([^"]*)"$/ + */ + public function userMovesFile($user, $fileSource, $fileDestination){ + $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav"; + $headers['Destination'] = $fullUrl . $fileDestination; + $this->makeDavRequest($user, "MOVE", $fileSource, $headers); } /** @@ -877,7 +967,9 @@ class FeatureContext implements Context, SnippetAcceptingContext { $fd = $body->getRowsHash(); foreach($fd as $field => $value) { - PHPUnit_Framework_Assert::assertEquals(True, $this->isFieldInResponse($field, $value)); + if (!$this->isFieldInResponse($field, $value)){ + PHPUnit_Framework_Assert::fail("$field" . " doesn't have value " . "$value"); + } } } } diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 07c05af2f54..aceff1de1a3 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -272,6 +272,36 @@ Feature: sharing | share_with_displayname | user1 | | displayname_owner | user0 | + Scenario: keep group permissions in sync + Given As an "admin" + Given user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And file "textfile0.txt" from user "user0" is shared with group "group1" + And User "user1" moved file "/textfile0.txt" to "/FOLDER/textfile0.txt" + And As an "user0" + When Updating last share with + | permissions | 1 | + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | file | + | item_source | A_NUMBER | + | share_type | 1 | + | file_source | A_NUMBER | + | file_target | /textfile0.txt | + | permissions | 1 | + | stime | A_NUMBER | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | displayname_owner | user0 | + Scenario: delete a share Given user "user0" exists And user "user1" exists diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature new file mode 100644 index 00000000000..450065ded2d --- /dev/null +++ b/build/integration/features/webdav-related.feature @@ -0,0 +1,20 @@ +Feature: sharing + Background: + Given using api version "1" + + Scenario: moving a file + Given As an "admin" + And user "user0" exists + When User "user0" moves file "/textfile0.txt" to "/FOLDER/textfile0.txt" + Then the HTTP status code should be "201" + + + + + + + + + + + -- GitLab From 630ba2fd0948b01db16b258a064bf3ca02302d1d Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Thu, 19 Nov 2015 09:36:56 +0000 Subject: [PATCH 085/344] Added test for shared_with_me parameter --- .../features/bootstrap/FeatureContext.php | 13 ++++++++++++- build/integration/features/sharing-v1.feature | 10 ++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 7176a19064a..56b81d631a7 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -800,7 +800,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { elseif($contentExpected == "AN_URL"){ return $this->isExpectedUrl((string)$element->$field, "index.php/s/"); } - elseif ($element->$field == $contentExpected){ + elseif ((string)$element->$field == $contentExpected){ return True; } } @@ -958,6 +958,17 @@ class FeatureContext implements Context, SnippetAcceptingContext { $this->sendingToWith("GET", $url, null); } + /** + * @Then /^last share_id is included in the answer$/ + */ + public function findingLastShareID(){ + print_r($this->response->xml()); + $share_id = $this->lastShareData->data[0]->id; + if (!$this->isFieldInResponse('id', $share_id)){ + PHPUnit_Framework_Assert::fail("Share id $share_id not found in response"); + } + } + /** * @Then /^Share fields of last share match with$/ * @param \Behat\Gherkin\Node\TableNode|null $formData diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index aceff1de1a3..0100ab3eda1 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -302,6 +302,16 @@ Feature: sharing | file_parent | A_NUMBER | | displayname_owner | user0 | + Scenario: Sharee can see the share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" from user "user0" is shared with user "user1" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is included in the answer + Scenario: delete a share Given user "user0" exists And user "user1" exists -- GitLab From 81e0a3ea2211cd2d3ea9d543c2523970be17867c Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Thu, 19 Nov 2015 10:28:38 +0000 Subject: [PATCH 086/344] Added test and logic for deleting all group shares --- .../features/bootstrap/FeatureContext.php | 13 +++++++++++-- build/integration/features/sharing-v1.feature | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 56b81d631a7..9daebd1e165 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -961,14 +961,23 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** * @Then /^last share_id is included in the answer$/ */ - public function findingLastShareID(){ - print_r($this->response->xml()); + public function checkingLastShareIDIsIncluded(){ $share_id = $this->lastShareData->data[0]->id; if (!$this->isFieldInResponse('id', $share_id)){ PHPUnit_Framework_Assert::fail("Share id $share_id not found in response"); } } + /** + * @Then /^last share_id is not included in the answer$/ + */ + public function checkingLastShareIDIsNotIncluded(){ + $share_id = $this->lastShareData->data[0]->id; + if ($this->isFieldInResponse('id', $share_id)){ + PHPUnit_Framework_Assert::fail("Share id $share_id has been found in response"); + } + } + /** * @Then /^Share fields of last share match with$/ * @param \Behat\Gherkin\Node\TableNode|null $formData diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 0100ab3eda1..6f62793f8df 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -312,6 +312,22 @@ Feature: sharing And the HTTP status code should be "200" And last share_id is included in the answer + Scenario: Delete all group shares + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And file "textfile0.txt" from user "user0" is shared with group "group1" + And User "user1" moved file "/textfile0.txt" to "/FOLDER/textfile0.txt" + And As an "user0" + And Deleting last share + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + Scenario: delete a share Given user "user0" exists And user "user1" exists -- GitLab From e342973888dcee658f5899f8b0cb0ed50d4ae9bc Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 26 Oct 2015 08:18:28 +0100 Subject: [PATCH 087/344] Bump 3rdparty for icewind/streams-0.3.0 --- 3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index be700d49186..5c7b1870477 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit be700d4918627e06eb3e8c5f3b025911061badff +Subproject commit 5c7b18704773473f8f7846ef942fc958f449c977 -- GitLab From ca6bd5cacd96ef04f5b940787575c5bdecfa756e Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Wed, 18 Nov 2015 17:32:09 +0100 Subject: [PATCH 088/344] Follow the interface again --- lib/private/files/stream/encryption.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php index e0d263d80b1..4c328993ef7 100644 --- a/lib/private/files/stream/encryption.php +++ b/lib/private/files/stream/encryption.php @@ -471,4 +471,13 @@ class Encryption extends Wrapper { return parent::stream_seek($position); } + /** + * @param string $path + * @param array $options + * @return bool + */ + public function dir_opendir($path, $options) { + return false; + } + } -- GitLab From ee4a18a16cd964338b417b0a312a6a67c54e7f53 Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Thu, 19 Nov 2015 14:17:56 +0000 Subject: [PATCH 089/344] added test about resharing --- .../features/bootstrap/FeatureContext.php | 4 +- build/integration/features/sharing-v1.feature | 37 +++++++++++++++---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 9daebd1e165..329b18d151c 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -599,10 +599,10 @@ class FeatureContext implements Context, SnippetAcceptingContext { } /** - * @When /^creating a public share with$/ + * @When /^creating a share with$/ * @param \Behat\Gherkin\Node\TableNode|null $formData */ - public function createPublicShare($body) { + public function creatingShare($body) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v1/shares"; $client = new Client(); $options = []; diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 6f62793f8df..0d64fcd8bcb 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -28,7 +28,7 @@ Feature: sharing Scenario: Creating a new public share Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | welcome.txt | | shareType | 3 | Then the OCS status code should be "100" @@ -38,7 +38,7 @@ Feature: sharing Scenario: Creating a new public share with password Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | welcome.txt | | shareType | 3 | | password | publicpw | @@ -49,7 +49,7 @@ Feature: sharing Scenario: Creating a new public share of a folder Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | FOLDER | | shareType | 3 | | password | publicpw | @@ -68,7 +68,7 @@ Feature: sharing Scenario: Creating a new public share with password and adding an expiration date Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | welcome.txt | | shareType | 3 | | password | publicpw | @@ -81,7 +81,7 @@ Feature: sharing Scenario: Creating a new public share, updating its expiration date and getting its info Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | FOLDER | | shareType | 3 | And Updating last share with @@ -111,7 +111,7 @@ Feature: sharing Scenario: Creating a new public share, updating its password and getting its info Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | FOLDER | | shareType | 3 | And Updating last share with @@ -140,7 +140,7 @@ Feature: sharing Scenario: Creating a new public share, updating its permissions and getting its info Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | FOLDER | | shareType | 3 | And Updating last share with @@ -169,7 +169,7 @@ Feature: sharing Scenario: Creating a new public share, updating publicUpload option and getting its info Given user "user0" exists And As an "user0" - When creating a public share with + When creating a share with | path | FOLDER | | shareType | 3 | And Updating last share with @@ -312,6 +312,27 @@ Feature: sharing And the HTTP status code should be "200" And last share_id is included in the answer + Scenario: User is not allowed to reshare file + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /textfile0.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 8 | + And As an "user1" + When creating a share with + | path | /textfile0. (2).txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Delete all group shares Given As an "admin" And user "user0" exists -- GitLab From 9ec2850c78e673a4aa1c4af97aa5be4414bd438f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 19 Nov 2015 15:35:58 +0100 Subject: [PATCH 090/344] Use mocks when testing isSharingDisabledForUser --- lib/private/files/storage/common.php | 2 +- lib/private/group/manager.php | 3 ++ lib/private/share/share.php | 2 +- lib/private/util.php | 22 ++++++---- lib/public/util.php | 6 ++- tests/lib/util.php | 66 +++++++++++++++------------- 6 files changed, 60 insertions(+), 41 deletions(-) diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index 77a70226b37..8e4958a930d 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -137,7 +137,7 @@ abstract class Common implements Storage { } public function isSharable($path) { - if (\OC_Util::isSharingDisabledForUser()) { + if (\OCP\Util::isSharingDisabledForUser()) { return false; } diff --git a/lib/private/group/manager.php b/lib/private/group/manager.php index 73ff0e537c6..40018370af5 100644 --- a/lib/private/group/manager.php +++ b/lib/private/group/manager.php @@ -214,6 +214,9 @@ class Manager extends PublicEmitter implements IGroupManager { * @return \OC\Group\Group[] */ public function getUserGroups($user) { + if (is_null($user)) { + return false; + } return $this->getUserIdGroups($user->getUID()); } diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 4503818a9ec..d377708a268 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -1811,7 +1811,7 @@ class Share extends Constants { } } // Check if resharing is allowed, if not remove share permission - if (isset($row['permissions']) && (!self::isResharingAllowed() | \OC_Util::isSharingDisabledForUser())) { + if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) { $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE; } // Add display names to result diff --git a/lib/private/util.php b/lib/private/util.php index 4c151d63639..8e3a0302513 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -54,6 +54,11 @@ * along with this program. If not, see * */ + +use OCP\IConfig; +use OCP\IGroupManager; +use OCP\IUser; + class OC_Util { public static $scripts = array(); public static $styles = array(); @@ -218,20 +223,21 @@ class OC_Util { /** * check if sharing is disabled for the current user - * - * @return boolean + * @param IConfig $config + * @param IGroupManager $groupManager + * @param IUser|null $user + * @return bool */ - public static function isSharingDisabledForUser() { - if (\OC::$server->getAppConfig()->getValue('core', 'shareapi_exclude_groups', 'no') === 'yes') { - $user = \OCP\User::getUser(); - $groupsList = \OC::$server->getAppConfig()->getValue('core', 'shareapi_exclude_groups_list', ''); + public static function isSharingDisabledForUser(IConfig $config, IGroupManager $groupManager, $user) { + if ($config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') { + $groupsList = $config->getAppValue('core', 'shareapi_exclude_groups_list', ''); $excludedGroups = json_decode($groupsList); if (is_null($excludedGroups)) { $excludedGroups = explode(',', $groupsList); $newValue = json_encode($excludedGroups); - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', $newValue); + $config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue); } - $usersGroups = \OC_Group::getUserGroups($user); + $usersGroups = $groupManager->getUserGroups($user); if (!empty($usersGroups)) { $remainingGroups = array_diff($usersGroups, $excludedGroups); // if the user is only in groups which are disabled for sharing then diff --git a/lib/public/util.php b/lib/public/util.php index 76b61347d46..07bc47c18b4 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -173,7 +173,11 @@ class Util { * @since 7.0.0 */ public static function isSharingDisabledForUser() { - return \OC_Util::isSharingDisabledForUser(); + return \OC_Util::isSharingDisabledForUser( + \OC::$server->getConfig(), + \OC::$server->getGroupManager(), + \OC::$server->getUserSession()->getUser() + ); } /** diff --git a/tests/lib/util.php b/tests/lib/util.php index 9974e799d08..cb575976f3f 100644 --- a/tests/lib/util.php +++ b/tests/lib/util.php @@ -289,38 +289,44 @@ class Test_Util extends \Test\TestCase { * @param bool $expected expected result */ function testIsSharingDisabledForUser($groups, $membership, $excludedGroups, $expected) { - $uid = "user1"; - \OC_User::setUserId($uid); - - \OC_User::createUser($uid, "passwd"); - - foreach ($groups as $group) { - \OC_Group::createGroup($group); - } - - foreach ($membership as $group) { - \OC_Group::addToGroup($uid, $group); - } - - $appConfig = \OC::$server->getAppConfig(); - $appConfig->setValue('core', 'shareapi_exclude_groups_list', json_encode($excludedGroups)); - $appConfig->setValue('core', 'shareapi_exclude_groups', 'yes'); - - $result = \OCP\Util::isSharingDisabledForUser(); + $config = $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(); + $groupManager = $this->getMockBuilder('OCP\IGroupManager')->disableOriginalConstructor()->getMock(); + $user = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); + + $config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_exclude_groups', 'no') + ->will($this->returnValue('yes')); + $config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('core', 'shareapi_exclude_groups_list') + ->will($this->returnValue(json_encode($excludedGroups))); + + $groupManager + ->expects($this->at(0)) + ->method('getUserGroups') + ->with($user) + ->will($this->returnValue($membership)); + +// $uid = "user1"; +// \OC_User::setUserId($uid); +// +// \OC_User::createUser($uid, "passwd"); +// +// foreach ($groups as $group) { +// \OC_Group::createGroup($group); +// } +// +// foreach ($membership as $group) { +// \OC_Group::addToGroup($uid, $group); +// } +// + + $result = \OC_Util::isSharingDisabledForUser($config, $groupManager, $user); $this->assertSame($expected, $result); - - // cleanup - \OC_User::deleteUser($uid); - \OC_User::setUserId(''); - - foreach ($groups as $group) { - \OC_Group::deleteGroup($group); - } - - $appConfig->setValue('core', 'shareapi_exclude_groups_list', ''); - $appConfig->setValue('core', 'shareapi_exclude_groups', 'no'); - } public function dataProviderForTestIsSharingDisabledForUser() { -- GitLab From 8fc0e05564195878c5ee2195ae54cd59058fe414 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 19 Nov 2015 14:39:41 +0100 Subject: [PATCH 091/344] Remove "Text file" entry in the "+" menu The text editor app will register this instead. Also made "fileList" a non-private attribute to make it possible for plugins to access the attached file list object. --- apps/files/js/newfilemenu.js | 20 +++---- apps/files/tests/js/newfilemenuSpec.js | 73 ++++++++++++++++++-------- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/apps/files/js/newfilemenu.js b/apps/files/js/newfilemenu.js index 175eb1d1a75..be7dcc40b6e 100644 --- a/apps/files/js/newfilemenu.js +++ b/apps/files/js/newfilemenu.js @@ -44,6 +44,11 @@ 'click .menuitem': '_onClickAction' }, + /** + * @type OCA.Files.FileList + */ + fileList: null, + initialize: function(options) { var self = this; var $uploadEl = $('#file_upload_start'); @@ -55,25 +60,16 @@ console.warn('Missing upload element "file_upload_start"'); } - this._fileList = options && options.fileList; + this.fileList = options && options.fileList; this._menuItems = [{ - id: 'file', - displayName: t('files', 'Text file'), - templateName: t('files', 'New text file.txt'), - iconClass: 'icon-filetype-text', - fileType: 'file', - actionHandler: function(name) { - self._fileList.createFile(name); - } - }, { id: 'folder', displayName: t('files', 'Folder'), templateName: t('files', 'New folder'), iconClass: 'icon-folder', fileType: 'folder', actionHandler: function(name) { - self._fileList.createDirectory(name); + self.fileList.createDirectory(name); } }]; @@ -149,7 +145,7 @@ try { if (!Files.isFileNameValid(filename)) { // Files.isFileNameValid(filename) throws an exception itself - } else if (self._fileList.inList(filename)) { + } else if (self.fileList.inList(filename)) { throw t('files', '{newname} already exists', {newname: filename}); } else { return true; diff --git a/apps/files/tests/js/newfilemenuSpec.js b/apps/files/tests/js/newfilemenuSpec.js index 3d89a997eb2..20f617d24d6 100644 --- a/apps/files/tests/js/newfilemenuSpec.js +++ b/apps/files/tests/js/newfilemenuSpec.js @@ -46,7 +46,7 @@ describe('OCA.Files.NewFileMenu', function() { describe('rendering', function() { it('renders menu items', function() { var $items = menu.$el.find('.menuitem'); - expect($items.length).toEqual(3); + expect($items.length).toEqual(2); // label points to the file_upload_start item var $item = $items.eq(0); expect($item.is('label')).toEqual(true); @@ -55,39 +55,26 @@ describe('OCA.Files.NewFileMenu', function() { }); describe('New file/folder', function() { var $input; - var createFileStub; var createDirectoryStub; beforeEach(function() { - createFileStub = sinon.stub(FileList.prototype, 'createFile'); createDirectoryStub = sinon.stub(FileList.prototype, 'createDirectory'); menu.$el.find('.menuitem').eq(1).click(); $input = menu.$el.find('form.filenameform input'); }); afterEach(function() { - createFileStub.restore(); createDirectoryStub.restore(); }); it('sets default text in field', function() { expect($input.length).toEqual(1); - expect($input.val()).toEqual('New text file.txt'); - }); - it('creates file when enter is pressed', function() { - $input.val('somefile.txt'); - $input.trigger(new $.Event('keyup', {keyCode: 13})); - $input.parent('form').submit(); - - expect(createFileStub.calledOnce).toEqual(true); - expect(createFileStub.getCall(0).args[0]).toEqual('somefile.txt'); - expect(createDirectoryStub.notCalled).toEqual(true); + expect($input.val()).toEqual('New folder'); }); it('prevents entering invalid file names', function() { $input.val('..'); $input.trigger(new $.Event('keyup', {keyCode: 13})); $input.closest('form').submit(); - expect(createFileStub.notCalled).toEqual(true); expect(createDirectoryStub.notCalled).toEqual(true); }); it('prevents entering file names that already exist', function() { @@ -96,16 +83,10 @@ describe('OCA.Files.NewFileMenu', function() { $input.trigger(new $.Event('keyup', {keyCode: 13})); $input.closest('form').submit(); - expect(createFileStub.notCalled).toEqual(true); expect(createDirectoryStub.notCalled).toEqual(true); inListStub.restore(); }); - it('switching fields removes the previous form', function() { - menu.$el.find('.menuitem').eq(2).click(); - expect(menu.$el.find('form').length).toEqual(1); - }); it('creates directory when clicking on create directory field', function() { - menu.$el.find('.menuitem').eq(2).click(); $input = menu.$el.find('form.filenameform input'); $input.val('some folder'); $input.trigger(new $.Event('keyup', {keyCode: 13})); @@ -113,7 +94,55 @@ describe('OCA.Files.NewFileMenu', function() { expect(createDirectoryStub.calledOnce).toEqual(true); expect(createDirectoryStub.getCall(0).args[0]).toEqual('some folder'); - expect(createFileStub.notCalled).toEqual(true); + }); + }); + describe('custom entries', function() { + var oldPlugins; + var plugin; + var actionStub; + + beforeEach(function() { + oldPlugins = _.extend({}, OC.Plugins._plugins); + actionStub = sinon.stub(); + plugin = { + attach: function(menu) { + menu.addMenuEntry({ + id: 'file', + displayName: t('files_texteditor', 'Text file'), + templateName: t('files_texteditor', 'New text file.txt'), + iconClass: 'icon-filetype-text', + fileType: 'file', + actionHandler: actionStub + }); + } + }; + + OC.Plugins.register('OCA.Files.NewFileMenu', plugin); + menu = new OCA.Files.NewFileMenu({ + fileList: fileList + }); + menu.showAt($trigger); + }); + afterEach(function() { + OC.Plugins._plugins = oldPlugins; + }); + it('renders custom menu items', function() { + expect(menu.$el.find('.menuitem').length).toEqual(3); + expect(menu.$el.find('.menuitem[data-action=file]').length).toEqual(1); + }); + it('calls action handler when clicking on custom item', function() { + menu.$el.find('.menuitem').eq(2).click(); + var $input = menu.$el.find('form.filenameform input'); + $input.val('some name'); + $input.trigger(new $.Event('keyup', {keyCode: 13})); + $input.closest('form').submit(); + + expect(actionStub.calledOnce).toEqual(true); + expect(actionStub.getCall(0).args[0]).toEqual('some name'); + }); + it('switching fields removes the previous form', function() { + menu.$el.find('.menuitem').eq(2).click(); + expect(menu.$el.find('form').length).toEqual(1); }); }); }); -- GitLab From ea2bf49be0cfa712572c029452bae7d553fc6fc1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 19 Nov 2015 16:08:21 +0100 Subject: [PATCH 092/344] Adjust the method name to reflect it's behaviour --- lib/public/systemtag/isystemtagobjectmapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/public/systemtag/isystemtagobjectmapper.php b/lib/public/systemtag/isystemtagobjectmapper.php index 87f3fd0473f..8c6c27c4846 100644 --- a/lib/public/systemtag/isystemtagobjectmapper.php +++ b/lib/public/systemtag/isystemtagobjectmapper.php @@ -110,6 +110,6 @@ interface ISystemTagObjectMapper { * * @since 9.0.0 */ - public function hasTags($objIds, $objectType, $tagId, $all = true); + public function haveTag($objIds, $objectType, $tagId, $all = true); } -- GitLab From c565a7b0429be19e98e42599c8ab7b6e4a46dc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 19 Nov 2015 16:20:27 +0100 Subject: [PATCH 093/344] Fix failing unit test :skull: --- lib/private/util.php | 2 +- tests/lib/util.php | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/private/util.php b/lib/private/util.php index 8e3a0302513..e48cdd4d9fc 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -237,7 +237,7 @@ class OC_Util { $newValue = json_encode($excludedGroups); $config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue); } - $usersGroups = $groupManager->getUserGroups($user); + $usersGroups = $groupManager->getUserGroupIds($user); if (!empty($usersGroups)) { $remainingGroups = array_diff($usersGroups, $excludedGroups); // if the user is only in groups which are disabled for sharing then diff --git a/tests/lib/util.php b/tests/lib/util.php index cb575976f3f..a328b1923e9 100644 --- a/tests/lib/util.php +++ b/tests/lib/util.php @@ -306,24 +306,10 @@ class Test_Util extends \Test\TestCase { $groupManager ->expects($this->at(0)) - ->method('getUserGroups') + ->method('getUserGroupIds') ->with($user) ->will($this->returnValue($membership)); -// $uid = "user1"; -// \OC_User::setUserId($uid); -// -// \OC_User::createUser($uid, "passwd"); -// -// foreach ($groups as $group) { -// \OC_Group::createGroup($group); -// } -// -// foreach ($membership as $group) { -// \OC_Group::addToGroup($uid, $group); -// } -// - $result = \OC_Util::isSharingDisabledForUser($config, $groupManager, $user); $this->assertSame($expected, $result); -- GitLab From ed039ee5ebdba6778b245f249fe206d2423a6a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 29 Oct 2015 17:27:14 +0100 Subject: [PATCH 094/344] added app "federation", allows you to connect ownClouds and exchange user lists --- .gitignore | 1 + apps/federation/appinfo/app.php | 25 ++ apps/federation/appinfo/application.php | 92 +++++++ apps/federation/appinfo/database.xml | 43 +++ apps/federation/appinfo/info.xml | 14 + apps/federation/appinfo/routes.php | 35 +++ .../controller/settingscontroller.php | 112 ++++++++ apps/federation/css/settings-admin.css | 24 ++ apps/federation/js/settings-admin.js | 70 +++++ apps/federation/lib/dbhandler.php | 147 +++++++++++ apps/federation/lib/trustedservers.php | 160 ++++++++++++ .../middleware/addservermiddleware.php | 71 +++++ apps/federation/settings/settings-admin.php | 39 +++ apps/federation/templates/settings-admin.php | 31 +++ .../controller/settingscontrollertest.php | 166 ++++++++++++ apps/federation/tests/lib/dbhandlertest.php | 130 ++++++++++ .../tests/lib/trustedserverstest.php | 244 ++++++++++++++++++ .../middleware/addservermiddlewaretest.php | 100 +++++++ tests/enable_all.php | 2 +- 19 files changed, 1505 insertions(+), 1 deletion(-) create mode 100644 apps/federation/appinfo/app.php create mode 100644 apps/federation/appinfo/application.php create mode 100644 apps/federation/appinfo/database.xml create mode 100644 apps/federation/appinfo/info.xml create mode 100644 apps/federation/appinfo/routes.php create mode 100644 apps/federation/controller/settingscontroller.php create mode 100644 apps/federation/css/settings-admin.css create mode 100644 apps/federation/js/settings-admin.js create mode 100644 apps/federation/lib/dbhandler.php create mode 100644 apps/federation/lib/trustedservers.php create mode 100644 apps/federation/middleware/addservermiddleware.php create mode 100644 apps/federation/settings/settings-admin.php create mode 100644 apps/federation/templates/settings-admin.php create mode 100644 apps/federation/tests/controller/settingscontrollertest.php create mode 100644 apps/federation/tests/lib/dbhandlertest.php create mode 100644 apps/federation/tests/lib/trustedserverstest.php create mode 100644 apps/federation/tests/middleware/addservermiddlewaretest.php diff --git a/.gitignore b/.gitignore index 531e372e607..3fb848dbb44 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ !/apps/dav !/apps/files !/apps/files_encryption +!/apps/federation !/apps/encryption !/apps/encryption_dummy !/apps/files_external diff --git a/apps/federation/appinfo/app.php b/apps/federation/appinfo/app.php new file mode 100644 index 00000000000..9ed00f23866 --- /dev/null +++ b/apps/federation/appinfo/app.php @@ -0,0 +1,25 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\AppInfo; + +$app = new Application(); +$app->registerSettings(); diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php new file mode 100644 index 00000000000..46a791c25d0 --- /dev/null +++ b/apps/federation/appinfo/application.php @@ -0,0 +1,92 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\AppInfo; + +use OCA\Federation\Controller\SettingsController; +use OCA\Federation\DbHandler; +use OCA\Federation\Middleware\AddServerMiddleware; +use OCA\Federation\TrustedServers; +use OCP\App; +use OCP\AppFramework\IAppContainer; +use OCP\IAppConfig; + +class Application extends \OCP\AppFramework\App { + + /** + * @param array $urlParams + */ + public function __construct($urlParams = array()) { + parent::__construct('federation', $urlParams); + $this->registerService(); + $this->registerMiddleware(); + + } + + /** + * register setting scripts + */ + public function registerSettings() { + App::registerAdmin('federation', 'settings/settings-admin'); + } + + private function registerService() { + $container = $this->getContainer(); + + $container->registerService('addServerMiddleware', function(IAppContainer $c) { + return new AddServerMiddleware( + $c->getAppName(), + \OC::$server->getL10N($c->getAppName()), + \OC::$server->getLogger() + ); + }); + + $container->registerService('DbHandler', function(IAppContainer $c) { + return new DbHandler( + \OC::$server->getDatabaseConnection(), + \OC::$server->getL10N($c->getAppName()) + ); + }); + + $container->registerService('TrustedServers', function(IAppContainer $c) { + return new TrustedServers( + $c->query('DbHandler'), + \OC::$server->getHTTPClientService(), + \OC::$server->getLogger() + ); + }); + + $container->registerService('SettingsController', function (IAppContainer $c) { + $server = $c->getServer(); + return new SettingsController( + $c->getAppName(), + $server->getRequest(), + $server->getL10N($c->getAppName()), + $c->query('TrustedServers') + ); + }); + } + + private function registerMiddleware() { + $container = $this->getContainer(); + $container->registerMiddleware('addServerMiddleware'); + } +} diff --git a/apps/federation/appinfo/database.xml b/apps/federation/appinfo/database.xml new file mode 100644 index 00000000000..da16212ca19 --- /dev/null +++ b/apps/federation/appinfo/database.xml @@ -0,0 +1,43 @@ + + + *dbname* + true + false + utf8 + + *dbprefix*trusted_servers + + + id + integer + 0 + true + 1 + 4 + + + url + text + true + 512 + Url of trusted server + + + url_hash + text + + true + 32 + md5 hash of the url + + + url_hash + true + + url_hash + ascending + + + +
+
diff --git a/apps/federation/appinfo/info.xml b/apps/federation/appinfo/info.xml new file mode 100644 index 00000000000..53b2926ba53 --- /dev/null +++ b/apps/federation/appinfo/info.xml @@ -0,0 +1,14 @@ + + + federation + Federation + 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. + AGPL + Bjoern Schiessle + 0.0.1 + Federation + other + + + + diff --git a/apps/federation/appinfo/routes.php b/apps/federation/appinfo/routes.php new file mode 100644 index 00000000000..43ccc4ed504 --- /dev/null +++ b/apps/federation/appinfo/routes.php @@ -0,0 +1,35 @@ + + * + * @copyright Copyright (c) 2015, 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 + * + */ + +return [ + 'routes' => [ + [ + 'name' => 'Settings#addServer', + 'url' => '/trusted-servers', + 'verb' => 'POST' + ], + [ + 'name' => 'Settings#removeServer', + 'url' => '/trusted-servers/{id}', + 'verb' => 'DELETE' + ], + ] +]; diff --git a/apps/federation/controller/settingscontroller.php b/apps/federation/controller/settingscontroller.php new file mode 100644 index 00000000000..8d522328120 --- /dev/null +++ b/apps/federation/controller/settingscontroller.php @@ -0,0 +1,112 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Controller; + +use OC\HintException; +use OCA\Federation\TrustedServers; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\IL10N; +use OCP\IRequest; + + +class SettingsController extends Controller { + + /** @var IL10N */ + private $l; + + /** @var TrustedServers */ + private $trustedServers; + + /** + * @param string $AppName + * @param IRequest $request + * @param IL10N $l10n + * @param TrustedServers $trustedServers + */ + public function __construct($AppName, + IRequest $request, + IL10N $l10n, + TrustedServers $trustedServers + ) { + parent::__construct($AppName, $request); + $this->l = $l10n; + $this->trustedServers = $trustedServers; + } + + + /** + * add server to the list of trusted ownClouds + * + * @param string $url + * @return DataResponse + * @throws HintException + */ + public function addServer($url) { + $this->checkServer($url); + $id = $this->trustedServers->addServer($url); + + return new DataResponse( + [ + 'url' => $url, + 'id' => $id, + 'message' => (string) $this->l->t('Server added to the list of trusted ownClouds') + ] + ); + } + + /** + * add server to the list of trusted ownClouds + * + * @param int $id + * @return DataResponse + */ + public function removeServer($id) { + $this->trustedServers->removeServer($id); + return new DataResponse(); + } + + /** + * check if the server should be added to the list of trusted servers or not + * + * @param string $url + * @return bool + * @throws HintException + */ + protected function checkServer($url) { + if ($this->trustedServers->isTrustedServer($url) === true) { + $message = 'Server is already in the list of trusted servers.'; + $hint = $this->l->t('Server is already in the list of trusted servers.'); + throw new HintException($message, $hint); + } + + if ($this->trustedServers->isOwnCloudServer($url) === false) { + $message = 'No ownCloud server found'; + $hint = $this->l->t('No ownCloud server found'); + throw new HintException($message, $hint); + } + + return true; + } + +} diff --git a/apps/federation/css/settings-admin.css b/apps/federation/css/settings-admin.css new file mode 100644 index 00000000000..7dbc949270f --- /dev/null +++ b/apps/federation/css/settings-admin.css @@ -0,0 +1,24 @@ +#ocFederationSettings p { + padding-top: 10px; +} + +#listOfTrustedServers li { + padding-top: 10px; + padding-left: 20px; +} + +.removeTrustedServer { + display: none; + vertical-align:middle; + padding-left: 10px; +} + +#ocFederationAddServerButton { + cursor: pointer; +} + +#listOfTrustedServers li:hover { + cursor: pointer; + background: url(../../../core/img/actions/delete.svg) no-repeat left center; + padding-left: 20px; +} diff --git a/apps/federation/js/settings-admin.js b/apps/federation/js/settings-admin.js new file mode 100644 index 00000000000..a1f02a09efe --- /dev/null +++ b/apps/federation/js/settings-admin.js @@ -0,0 +1,70 @@ +/** + * @author Björn Schießle + * + * @copyright Copyright (c) 2015, 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 + * + */ + +$(document).ready(function () { + + // show input field to add a new trusted server + $("#ocFederationAddServer").on('click', function() { + $('#ocFederationAddServerButton').addClass('hidden'); + $("#serverUrl").removeClass('hidden'); + $("#serverUrl").focus(); + }); + + // add new trusted server + $("#serverUrl").keyup(function (e) { + if (e.keyCode === 13) { // add server on "enter" + var url = $('#serverUrl').val(); + OC.msg.startSaving('#ocFederationAddServer .msg'); + $.post( + OC.generateUrl('/apps/federation/trusted-servers'), + { + url: url + } + ).done(function (data) { + $('#serverUrl').attr('value', ''); + $('ul#listOfTrustedServers').prepend( + $('
  • ').attr('id', data.id).text(data.url) + ); + OC.msg.finishedSuccess('#ocFederationAddServer .msg', data.message); + }) + .fail(function (jqXHR) { + OC.msg.finishedError('#ocFederationAddServer .msg', JSON.parse(jqXHR.responseText).message); + }); + } else if (e.keyCode === 27) { // hide input filed again in ESC + $('#ocFederationAddServerButton').toggleClass('hidden'); + $("#serverUrl").toggleClass('hidden'); + } + }); + + // remove trusted server from list + $( "#listOfTrustedServers" ).on('click', 'li', function() { + var id = $(this).attr('id'); + var $this = $(this); + $.ajax({ + url: OC.generateUrl('/apps/federation/trusted-servers/' + id), + type: 'DELETE', + success: function(response) { + $this.remove(); + } + }); + + }); + +}); diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php new file mode 100644 index 00000000000..1100875cc23 --- /dev/null +++ b/apps/federation/lib/dbhandler.php @@ -0,0 +1,147 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation; + + +use OC\HintException; +use OCP\IDBConnection; +use OCP\IL10N; + +class DbHandler { + + /** @var IDBConnection */ + private $connection; + + /** @var IL10N */ + private $l; + + /** @var string */ + private $dbTable = 'trusted_servers'; + + /** + * @param IDBConnection $connection + * @param IL10N $il10n + */ + public function __construct( + IDBConnection $connection, + IL10N $il10n + ) { + $this->connection = $connection; + $this->IL10N = $il10n; + } + + /** + * add server to the list of trusted ownCloud servers + * + * @param $url + * @return int + * @throws HintException + */ + public function add($url) { + $hash = md5($url); + $query = $this->connection->getQueryBuilder(); + $query->insert($this->dbTable) + ->values( + [ + 'url' => $query->createParameter('url'), + 'url_hash' => $query->createParameter('url_hash'), + ] + ) + ->setParameter('url', $url) + ->setParameter('url_hash', $hash); + + $result = $query->execute(); + + if ($result) { + $id = $this->connection->lastInsertId(); + // Fallback, if lastInterId() doesn't work we need to perform a select + // to get the ID (seems to happen sometimes on Oracle) + if (!$id) { + $server = $this->get($url); + $id = $server['id']; + } + return $id; + } else { + $message = 'Internal failure, Could not add ownCloud as trusted server: ' . $url; + $message_t = $this->l->t('Could not add server'); + throw new HintException($message, $message_t); + } + } + + /** + * remove server from the list of trusted ownCloud servers + * + * @param int $id + */ + public function remove($id) { + $query = $this->connection->getQueryBuilder(); + $query->delete($this->dbTable) + ->where($query->expr()->eq('id', $query->createParameter('id'))) + ->setParameter('id', $id); + $query->execute(); + } + + /** + * get trusted server from database + * + * @param $url + * @return mixed + */ + public function get($url) { + $query = $this->connection->getQueryBuilder(); + $query->select('url', 'id')->from($this->dbTable) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', md5($url)); + + return $query->execute()->fetch(); + } + + /** + * get all trusted servers + * + * @return array + */ + public function getAll() { + $query = $this->connection->getQueryBuilder(); + $query->select('url', 'id')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + return $result; + } + + /** + * check if server already exists in the database table + * + * @param string $url + * @return bool + */ + public function exists($url) { + $query = $this->connection->getQueryBuilder(); + $query->select('url')->from($this->dbTable) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', md5($url)); + $result = $query->execute()->fetchAll(); + + return !empty($result); + } + +} diff --git a/apps/federation/lib/trustedservers.php b/apps/federation/lib/trustedservers.php new file mode 100644 index 00000000000..bf31277b2a8 --- /dev/null +++ b/apps/federation/lib/trustedservers.php @@ -0,0 +1,160 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation; + + +use OC\Files\Filesystem; +use OCP\AppFramework\Http; +use OCP\Http\Client\IClientService; +use OCP\IDBConnection; +use OCP\ILogger; + +class TrustedServers { + + /** @var dbHandler */ + private $dbHandler; + + /** @var IClientService */ + private $httpClientService; + + /** @var ILogger */ + private $logger; + + private $dbTable = 'trusted_servers'; + + /** + * @param DbHandler $dbHandler + * @param IClientService $httpClientService + * @param ILogger $logger + */ + public function __construct( + DbHandler $dbHandler, + IClientService $httpClientService, + ILogger $logger + ) { + $this->dbHandler = $dbHandler; + $this->httpClientService = $httpClientService; + $this->logger = $logger; + } + + /** + * add server to the list of trusted ownCloud servers + * + * @param $url + * @return int server id + */ + public function addServer($url) { + return $this->dbHandler->add($this->normalizeUrl($url)); + } + + /** + * remove server from the list of trusted ownCloud servers + * + * @param int $id + */ + public function removeServer($id) { + $this->dbHandler->remove($id); + } + + /** + * get all trusted servers + * + * @return array + */ + public function getServers() { + return $this->dbHandler->getAll(); + } + + /** + * check if given server is a trusted ownCloud server + * + * @param string $url + * @return bool + */ + public function isTrustedServer($url) { + return $this->dbHandler->exists($this->normalizeUrl($url)); + } + + /** + * check if URL point to a ownCloud server + * + * @param string $url + * @return bool + */ + public function isOwnCloudServer($url) { + $isValidOwnCloud = false; + $client = $this->httpClientService->newClient(); + try { + $result = $client->get( + $url . '/status.php', + [ + 'timeout' => 3, + 'connect_timeout' => 3, + ] + ); + if ($result->getStatusCode() === Http::STATUS_OK) { + $isValidOwnCloud = $this->checkOwnCloudVersion($result->getBody()); + } + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), ['app' => 'federation']); + return false; + } + return $isValidOwnCloud; + } + + /** + * check if ownCloud version is >= 9.0 + * + * @param $statusphp + * @return bool + */ + protected function checkOwnCloudVersion($statusphp) { + $decoded = json_decode($statusphp, true); + if (!empty($decoded) && isset($decoded['version'])) { + return version_compare($decoded['version'], '9.0.0', '>='); + } + return false; + } + + /** + * normalize URL + * + * @param string $url + * @return string + */ + protected function normalizeUrl($url) { + + $normalized = $url; + + if (strpos($url, 'https://') === 0) { + $normalized = substr($url, strlen('https://')); + } else if (strpos($url, 'http://') === 0) { + $normalized = substr($url, strlen('http://')); + } + + $normalized = Filesystem::normalizePath($normalized); + $normalized = trim($normalized, '/'); + + return $normalized; + } +} diff --git a/apps/federation/middleware/addservermiddleware.php b/apps/federation/middleware/addservermiddleware.php new file mode 100644 index 00000000000..56552021dc2 --- /dev/null +++ b/apps/federation/middleware/addservermiddleware.php @@ -0,0 +1,71 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Middleware ; + +use OC\HintException; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Middleware; +use OCP\IL10N; +use OCP\ILogger; + +class AddServerMiddleware extends Middleware { + + /** @var string */ + protected $appName; + + /** @var IL10N */ + protected $l; + + /** @var ILogger */ + protected $logger; + + public function __construct($appName, IL10N $l, ILogger $logger) { + $this->appName = $appName; + $this->l = $l; + $this->logger = $logger; + } + + /** + * Log error message and return a response which can be displayed to the user + * + * @param \OCP\AppFramework\Controller $controller + * @param string $methodName + * @param \Exception $exception + * @return JSONResponse + */ + public function afterException($controller, $methodName, \Exception $exception) { + $this->logger->error($exception->getMessage(), ['app' => $this->appName]); + if ($exception instanceof HintException) { + $message = $exception->getHint(); + } else { + $message = $this->l->t('Unknown error'); + } + + return new JSONResponse( + ['message' => $message], + Http::STATUS_BAD_REQUEST + ); + + } + +} diff --git a/apps/federation/settings/settings-admin.php b/apps/federation/settings/settings-admin.php new file mode 100644 index 00000000000..ea71475d619 --- /dev/null +++ b/apps/federation/settings/settings-admin.php @@ -0,0 +1,39 @@ + + * + * @copyright Copyright (c) 2015, 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 + * + */ + +\OC_Util::checkAdminUser(); + +$template = new OCP\Template('federation', 'settings-admin'); + +$dbHandler = new \OCA\Federation\DbHandler( + \OC::$server->getDatabaseConnection(), + \OC::$server->getL10N('federation') +); + +$trustedServers = new \OCA\Federation\TrustedServers( + $dbHandler, + \OC::$server->getHTTPClientService(), + \OC::$server->getLogger() +); + +$template->assign('trustedServers', $trustedServers->getServers()); + +return $template->fetchPage(); diff --git a/apps/federation/templates/settings-admin.php b/apps/federation/templates/settings-admin.php new file mode 100644 index 00000000000..faa1e393158 --- /dev/null +++ b/apps/federation/templates/settings-admin.php @@ -0,0 +1,31 @@ + +
    +

    t('Federation')); ?>

    + t('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.')); ?> + +

    + + +

    + +

    Trusted ownCloud Servers

    +

    + + + +

    +
      + +
    • + +
    • + +
    + +
    + diff --git a/apps/federation/tests/controller/settingscontrollertest.php b/apps/federation/tests/controller/settingscontrollertest.php new file mode 100644 index 00000000000..efbc6911c52 --- /dev/null +++ b/apps/federation/tests/controller/settingscontrollertest.php @@ -0,0 +1,166 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\Controller; + + +use OCA\Federation\Controller\SettingsController; +use OCP\AppFramework\Http\DataResponse; +use Test\TestCase; + +class SettingsControllerTest extends TestCase { + + /** @var SettingsController */ + private $controller; + + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IRequest */ + private $request; + + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IL10N */ + private $l10n; + + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Federation\TrustedServers */ + private $trustedServers; + + public function setUp() { + parent::setUp(); + + $this->request = $this->getMock('OCP\IRequest'); + $this->l10n = $this->getMock('OCP\IL10N'); + $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->disableOriginalConstructor()->getMock(); + + $this->controller = new SettingsController( + 'SettingsControllerTest', + $this->request, + $this->l10n, + $this->trustedServers + ); + } + + public function testAddServer() { + $this->trustedServers + ->expects($this->once()) + ->method('isTrustedServer') + ->with('url') + ->willReturn(false); + $this->trustedServers + ->expects($this->once()) + ->method('isOwnCloudServer') + ->with('url') + ->willReturn(true); + + $result = $this->controller->addServer('url'); + $this->assertTrue($result instanceof DataResponse); + + $data = $result->getData(); + $this->assertSame(200, $result->getStatus()); + $this->assertSame('url', $data['url']); + $this->assertArrayHasKey('id', $data); + } + + /** + * @dataProvider checkServerFails + * @expectedException \OC\HintException + * + * @param bool $isTrustedServer + * @param bool $isOwnCloud + */ + public function testAddServerFail($isTrustedServer, $isOwnCloud) { + $this->trustedServers + ->expects($this->any()) + ->method('isTrustedServer') + ->with('url') + ->willReturn($isTrustedServer); + $this->trustedServers + ->expects($this->any()) + ->method('isOwnCloudServer') + ->with('url') + ->willReturn($isOwnCloud); + + $this->controller->addServer('url'); + } + + public function testRemoveServer() { + $this->trustedServers->expects($this->once())->method('removeServer') + ->with('url'); + $result = $this->controller->removeServer('url'); + $this->assertTrue($result instanceof DataResponse); + $this->assertSame(200, $result->getStatus()); + } + + public function testCheckServer() { + $this->trustedServers + ->expects($this->once()) + ->method('isTrustedServer') + ->with('url') + ->willReturn(false); + $this->trustedServers + ->expects($this->once()) + ->method('isOwnCloudServer') + ->with('url') + ->willReturn(true); + + $this->assertTrue( + $this->invokePrivate($this->controller, 'checkServer', ['url']) + ); + + } + + /** + * @dataProvider checkServerFails + * @expectedException \OC\HintException + * + * @param bool $isTrustedServer + * @param bool $isOwnCloud + */ + public function testCheckServerFail($isTrustedServer, $isOwnCloud) { + $this->trustedServers + ->expects($this->any()) + ->method('isTrustedServer') + ->with('url') + ->willReturn($isTrustedServer); + $this->trustedServers + ->expects($this->any()) + ->method('isOwnCloudServer') + ->with('url') + ->willReturn($isOwnCloud); + + $this->assertTrue( + $this->invokePrivate($this->controller, 'checkServer', ['url']) + ); + + } + + /** + * data to simulate checkServer fails + * + * @return array + */ + public function checkServerFails() { + return [ + [true, true], + [false, false] + ]; + } + +} diff --git a/apps/federation/tests/lib/dbhandlertest.php b/apps/federation/tests/lib/dbhandlertest.php new file mode 100644 index 00000000000..202199d2b5b --- /dev/null +++ b/apps/federation/tests/lib/dbhandlertest.php @@ -0,0 +1,130 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\lib; + + +use OCA\Federation\DbHandler; +use OCP\IDBConnection; +use Test\TestCase; + +class DbHandlerTest extends TestCase { + + /** @var DbHandler */ + private $dbHandler; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $il10n; + + /** @var IDBConnection */ + private $connection; + + /** @var string */ + private $dbTable = 'trusted_servers'; + + public function setUp() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + $this->il10n = $this->getMock('OCP\IL10N'); + + $this->dbHandler = new DbHandler( + $this->connection, + $this->il10n + ); + + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertEmpty($result, 'we need to start with a empty trusted_servers table'); + } + + public function tearDown() { + parent::tearDown(); + $query = $this->connection->getQueryBuilder()->delete($this->dbTable); + $query->execute(); + } + + public function testAdd() { + $id = $this->dbHandler->add('server1'); + + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame('server1', $result[0]['url']); + $this->assertSame($id, $result[0]['id']); + } + + public function testRemove() { + $id1 = $this->dbHandler->add('server1'); + $id2 = $this->dbHandler->add('server2'); + + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(2, count($result)); + $this->assertSame('server1', $result[0]['url']); + $this->assertSame('server2', $result[1]['url']); + $this->assertSame($id1, $result[0]['id']); + $this->assertSame($id2, $result[1]['id']); + + $this->dbHandler->remove($id2); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame('server1', $result[0]['url']); + $this->assertSame($id1, $result[0]['id']); + } + + public function testGetAll() { + $id1 = $this->dbHandler->add('server1'); + $id2 = $this->dbHandler->add('server2'); + + $result = $this->dbHandler->getAll(); + $this->assertSame(2, count($result)); + $this->assertSame('server1', $result[0]['url']); + $this->assertSame('server2', $result[1]['url']); + $this->assertSame($id1, $result[0]['id']); + $this->assertSame($id2, $result[1]['id']); + } + + /** + * @dataProvider dataTestExists + * + * @param string $serverInTable + * @param string $checkForServer + * @param bool $expected + */ + public function testExists($serverInTable, $checkForServer, $expected) { + $this->dbHandler->add($serverInTable); + $this->assertSame($expected, + $this->dbHandler->exists($checkForServer) + ); + } + + public function dataTestExists() { + return [ + ['server1', 'server1', true], + ['server1', 'server1', true], + ['server1', 'server2', false] + ]; + } + +} diff --git a/apps/federation/tests/lib/trustedserverstest.php b/apps/federation/tests/lib/trustedserverstest.php new file mode 100644 index 00000000000..07aa7531274 --- /dev/null +++ b/apps/federation/tests/lib/trustedserverstest.php @@ -0,0 +1,244 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\lib; + + +use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; +use OCP\Http\Client\IClient; +use OCP\Http\Client\IClientService; +use OCP\Http\Client\IResponse; +use OCP\IDBConnection; +use OCP\ILogger; +use Test\TestCase; + +class TrustedServersTest extends TestCase { + + /** @var TrustedServers */ + private $trustedServers; + + /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */ + private $dbHandler; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IClientService */ + private $httpClientService; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IClient */ + private $httpClient; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */ + private $response; + + /** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */ + private $logger; + + public function setUp() { + parent::setUp(); + + $this->dbHandler = $this->getMockBuilder('\OCA\Federation\DbHandler') + ->disableOriginalConstructor()->getMock(); + $this->httpClientService = $this->getMock('OCP\Http\Client\IClientService'); + $this->httpClient = $this->getMock('OCP\Http\Client\IClient'); + $this->response = $this->getMock('OCP\Http\Client\IResponse'); + $this->logger = $this->getMock('OCP\ILogger'); + + $this->trustedServers = new TrustedServers( + $this->dbHandler, + $this->httpClientService, + $this->logger + ); + + } + + public function testAddServer() { + /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ + $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->setConstructorArgs( + [ + $this->dbHandler, + $this->httpClientService, + $this->logger + ] + ) + ->setMethods(['normalizeUrl']) + ->getMock(); + $trustedServers->expects($this->once())->method('normalizeUrl') + ->with('url')->willReturn('normalized'); + $this->dbHandler->expects($this->once())->method('add')->with('normalized') + ->willReturn(true); + + $this->assertTrue( + $trustedServers->addServer('url') + ); + } + + public function testRemoveServer() { + $id = 42; + $this->dbHandler->expects($this->once())->method('remove')->with($id); + $this->trustedServers->removeServer($id); + } + + public function testGetServers() { + $this->dbHandler->expects($this->once())->method('getAll')->willReturn(true); + + $this->assertTrue( + $this->trustedServers->getServers() + ); + } + + + public function testIsTrustedServer() { + /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ + $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->setConstructorArgs( + [ + $this->dbHandler, + $this->httpClientService, + $this->logger + ] + ) + ->setMethods(['normalizeUrl']) + ->getMock(); + $trustedServers->expects($this->once())->method('normalizeUrl') + ->with('url')->willReturn('normalized'); + $this->dbHandler->expects($this->once())->method('exists')->with('normalized') + ->willReturn(true); + + $this->assertTrue( + $trustedServers->isTrustedServer('url') + ); + } + + /** + * @dataProvider dataTestIsOwnCloudServer + * + * @param int $statusCode + * @param bool $isValidOwnCloudVersion + * @param bool $expected + */ + public function testIsOwnCloudServer($statusCode, $isValidOwnCloudVersion, $expected) { + + $server = 'server1'; + + /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ + $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->setConstructorArgs( + [ + $this->dbHandler, + $this->httpClientService, + $this->logger + ] + ) + ->setMethods(['checkOwnCloudVersion']) + ->getMock(); + + $this->httpClientService->expects($this->once())->method('newClient') + ->willReturn($this->httpClient); + + $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php') + ->willReturn($this->response); + + $this->response->expects($this->once())->method('getStatusCode') + ->willReturn($statusCode); + + if ($statusCode === 200) { + $trustedServers->expects($this->once())->method('checkOwnCloudVersion') + ->willReturn($isValidOwnCloudVersion); + } else { + $trustedServers->expects($this->never())->method('checkOwnCloudVersion'); + } + + $this->assertSame($expected, + $trustedServers->isOwnCloudServer($server) + ); + + } + + public function dataTestIsOwnCloudServer() { + return [ + [200, true, true], + [200, false, false], + [404, true, false], + ]; + } + + public function testIsOwnCloudServerFail() { + $server = 'server1'; + + $this->httpClientService->expects($this->once())->method('newClient') + ->willReturn($this->httpClient); + + $this->logger->expects($this->once())->method('error') + ->with('simulated exception', ['app' => 'federation']); + + $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php') + ->willReturnCallback(function() { + throw new \Exception('simulated exception'); + }); + + $this->assertFalse($this->trustedServers->isOwnCloudServer($server)); + + } + + /** + * @dataProvider dataTestCheckOwnCloudVersion + * + * @param $statusphp + * @param $expected + */ + public function testCheckOwnCloudVersion($statusphp, $expected) { + $this->assertSame($expected, + $this->invokePrivate($this->trustedServers, 'checkOwnCloudVersion', [$statusphp]) + ); + } + + public function dataTestCheckOwnCloudVersion() { + return [ + ['{"version":"8.4.0"}', false], + ['{"version":"9.0.0"}', true], + ['{"version":"9.1.0"}', true] + ]; + } + + /** + * @dataProvider dataTestNormalizeUrl + * + * @param string $url + * @param string $expected + */ + public function testNormalizeUrl($url, $expected) { + $this->assertSame($expected, + $this->invokePrivate($this->trustedServers, 'normalizeUrl', [$url]) + ); + } + + public function dataTestNormalizeUrl() { + return [ + ['owncloud.org', 'owncloud.org'], + ['http://owncloud.org', 'owncloud.org'], + ['https://owncloud.org', 'owncloud.org'], + ['https://owncloud.org//mycloud', 'owncloud.org/mycloud'], + ['https://owncloud.org/mycloud/', 'owncloud.org/mycloud'], + ]; + } +} diff --git a/apps/federation/tests/middleware/addservermiddlewaretest.php b/apps/federation/tests/middleware/addservermiddlewaretest.php new file mode 100644 index 00000000000..1be5a342285 --- /dev/null +++ b/apps/federation/tests/middleware/addservermiddlewaretest.php @@ -0,0 +1,100 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\Middleware; + + +use OC\HintException; +use OCA\Federation\Middleware\AddServerMiddleware; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use Test\TestCase; + +class AddServerMiddlewareTest extends TestCase { + + /** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */ + private $logger; + + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IL10N */ + private $l10n; + + /** @var AddServerMiddleware */ + private $middleware; + + /** @var \PHPUnit_Framework_MockObject_MockObject | Controller */ + private $controller; + + public function setUp() { + parent::setUp(); + + $this->logger = $this->getMock('OCP\ILogger'); + $this->l10n = $this->getMock('OCP\IL10N'); + $this->controller = $this->getMockBuilder('OCP\AppFramework\Controller') + ->disableOriginalConstructor()->getMock(); + + $this->middleware = new AddServerMiddleware( + 'AddServerMiddlewareTest', + $this->l10n, + $this->logger + ); + } + + /** + * @dataProvider dataTestAfterException + * + * @param \Exception $exception + * @param string $message + * @param string $hint + */ + public function testAfterException($exception, $message, $hint) { + + $this->logger->expects($this->once())->method('error') + ->with($message, ['app' => 'AddServerMiddlewareTest']); + + $this->l10n->expects($this->any())->method('t') + ->willReturnCallback( + function($message) { + return $message; + } + ); + + $result = $this->middleware->afterException($this->controller, 'method', $exception); + + $this->assertSame(Http::STATUS_BAD_REQUEST, + $result->getStatus() + ); + + $data = $result->getData(); + + $this->assertSame($hint, + $data['message'] + ); + } + + public function dataTestAfterException() { + return [ + [new HintException('message', 'hint'), 'message', 'hint'], + [new \Exception('message'), 'message', 'Unknown error'], + ]; + } + +} diff --git a/tests/enable_all.php b/tests/enable_all.php index 464155b1f39..6f2d1fa8717 100644 --- a/tests/enable_all.php +++ b/tests/enable_all.php @@ -22,4 +22,4 @@ enableApp('encryption'); enableApp('user_ldap'); enableApp('files_versions'); enableApp('provisioning_api'); - +enableApp('federation'); -- GitLab From 698100d279fdd8c8bc086e729833705d1a31c018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 10 Nov 2015 10:50:59 +0100 Subject: [PATCH 095/344] exchange shared secret --- apps/federation/api/ocsauthapi.php | 136 +++++++++++++ apps/federation/appinfo/application.php | 56 +++++- apps/federation/appinfo/database.xml | 22 ++- apps/federation/appinfo/routes.php | 35 ++-- .../backgroundjob/getsharedsecret.php | 155 +++++++++++++++ .../backgroundjob/requestsharedsecret.php | 134 +++++++++++++ apps/federation/lib/dbhandler.php | 182 ++++++++++++++--- apps/federation/lib/trustedservers.php | 105 ++++++++-- apps/federation/settings/settings-admin.php | 4 +- apps/federation/tests/api/ocsauthapitest.php | 184 ++++++++++++++++++ apps/federation/tests/lib/dbhandlertest.php | 45 ++++- .../tests/lib/trustedserverstest.php | 113 +++++++---- 12 files changed, 1052 insertions(+), 119 deletions(-) create mode 100644 apps/federation/api/ocsauthapi.php create mode 100644 apps/federation/backgroundjob/getsharedsecret.php create mode 100644 apps/federation/backgroundjob/requestsharedsecret.php create mode 100644 apps/federation/tests/api/ocsauthapitest.php diff --git a/apps/federation/api/ocsauthapi.php b/apps/federation/api/ocsauthapi.php new file mode 100644 index 00000000000..7965e6f2140 --- /dev/null +++ b/apps/federation/api/ocsauthapi.php @@ -0,0 +1,136 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\API; + +use OC\BackgroundJob\JobList; +use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; +use OCP\AppFramework\Http; +use OCP\IRequest; +use OCP\Security\ISecureRandom; +use OCP\Security\StringUtils; + +/** + * Class OCSAuthAPI + * + * OCS API end-points to exchange shared secret between two connected ownClouds + * + * @package OCA\Federation\API + */ +class OCSAuthAPI { + + /** @var IRequest */ + private $request; + + /** @var ISecureRandom */ + private $secureRandom; + + /** @var JobList */ + private $jobList; + + /** @var TrustedServers */ + private $trustedServers; + + /** @var DbHandler */ + private $dbHandler; + + /** + * AuthController constructor. + * + * @param IRequest $request + * @param ISecureRandom $secureRandom + * @param JobList $jobList + * @param TrustedServers $trustedServers + * @param DbHandler $dbHandler + */ + public function __construct( + IRequest $request, + ISecureRandom $secureRandom, + JobList $jobList, + TrustedServers $trustedServers, + DbHandler $dbHandler + ) { + $this->request = $request; + $this->secureRandom = $secureRandom; + $this->jobList = $jobList; + $this->trustedServers = $trustedServers; + $this->dbHandler = $dbHandler; + } + + /** + * request received to ask remote server for a shared secret + * + * @return \OC_OCS_Result + */ + public function requestSharedSecret() { + + $url = $this->request->getParam('url'); + $token = $this->request->getParam('token'); + + if ($this->trustedServers->isTrustedServer($url) === false) { + return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN); + } + + $this->jobList->add( + 'OCA\Federation\BackgroundJob\GetSharedSecret', + [ + 'url' => $url, + 'token' => $token, + ] + ); + + return new \OC_OCS_Result(null, Http::STATUS_OK); + + } + + /** + * create shared secret and return it + * + * @return \OC_OCS_Result + */ + public function getSharedSecret() { + + $url = $this->request->getParam('url'); + $token = $this->request->getParam('token'); + + if ( + $this->trustedServers->isTrustedServer($url) === false + || $this->isValidToken($url, $token) === false + ) { + return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN); + } + + $sharedSecret = $this->secureRandom->getMediumStrengthGenerator()->generate(32); + + $this->trustedServers->addSharedSecret($url, $sharedSecret); + + return new \OC_OCS_Result(['sharedSecret' => $sharedSecret], Http::STATUS_OK); + + } + + protected function isValidToken($url, $token) { + $storedToken = $this->dbHandler->getToken($url); + return StringUtils::equals($storedToken, $token); + } + +} diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php index 46a791c25d0..e91506a30bd 100644 --- a/apps/federation/appinfo/application.php +++ b/apps/federation/appinfo/application.php @@ -21,13 +21,15 @@ namespace OCA\Federation\AppInfo; +use OCA\Federation\API\OCSAuthAPI; +use OCA\Federation\Controller\AuthController; use OCA\Federation\Controller\SettingsController; use OCA\Federation\DbHandler; use OCA\Federation\Middleware\AddServerMiddleware; use OCA\Federation\TrustedServers; +use OCP\API; use OCP\App; use OCP\AppFramework\IAppContainer; -use OCP\IAppConfig; class Application extends \OCP\AppFramework\App { @@ -38,7 +40,6 @@ class Application extends \OCP\AppFramework\App { parent::__construct('federation', $urlParams); $this->registerService(); $this->registerMiddleware(); - } /** @@ -70,7 +71,9 @@ class Application extends \OCP\AppFramework\App { return new TrustedServers( $c->query('DbHandler'), \OC::$server->getHTTPClientService(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getJobList(), + \OC::$server->getSecureRandom() ); }); @@ -83,10 +86,57 @@ class Application extends \OCP\AppFramework\App { $c->query('TrustedServers') ); }); + + + $container->registerService('AuthController', function (IAppContainer $c) { + $server = $c->getServer(); + return new AuthController( + $c->getAppName(), + $server->getRequest(), + $server->getSecureRandom(), + $server->getJobList(), + $c->query('TrustedServers'), + $c->query('DbHandler') + ); + }); } private function registerMiddleware() { $container = $this->getContainer(); $container->registerMiddleware('addServerMiddleware'); } + + /** + * register OCS API Calls + */ + public function registerOCSApi() { + + $container = $this->getContainer(); + $server = $container->getServer(); + + $auth = new OCSAuthAPI( + $server->getRequest(), + $server->getSecureRandom(), + $server->getJobList(), + $container->query('TrustedServers'), + $container->query('DbHandler') + + ); + + API::register('get', + '/apps/federation/api/v1/shared-secret', + array($auth, 'getSharedSecret'), + 'federation', + API::GUEST_AUTH + ); + + API::register('post', + '/apps/federation/api/v1/request-shared-secret', + array($auth, 'requestSharedSecret'), + 'federation', + API::GUEST_AUTH + ); + + } + } diff --git a/apps/federation/appinfo/database.xml b/apps/federation/appinfo/database.xml index da16212ca19..e0bb241918e 100644 --- a/apps/federation/appinfo/database.xml +++ b/apps/federation/appinfo/database.xml @@ -28,7 +28,27 @@ true 32 - md5 hash of the url + md5 hash of the url without the protocol + + + token + text + 128 + toke used to exchange the shared secret + + + shared_secret + text + 256 + shared secret used to authenticate + + + status + integer + 4 + true + 2 + current status of the connection url_hash diff --git a/apps/federation/appinfo/routes.php b/apps/federation/appinfo/routes.php index 43ccc4ed504..f45db43e4e7 100644 --- a/apps/federation/appinfo/routes.php +++ b/apps/federation/appinfo/routes.php @@ -19,17 +19,24 @@ * */ -return [ - 'routes' => [ - [ - 'name' => 'Settings#addServer', - 'url' => '/trusted-servers', - 'verb' => 'POST' - ], - [ - 'name' => 'Settings#removeServer', - 'url' => '/trusted-servers/{id}', - 'verb' => 'DELETE' - ], - ] -]; +$application = new \OCA\Federation\AppInfo\Application(); + +$application->registerRoutes( + $this, + [ + 'routes' => [ + [ + 'name' => 'Settings#addServer', + 'url' => '/trusted-servers', + 'verb' => 'POST' + ], + [ + 'name' => 'Settings#removeServer', + 'url' => '/trusted-servers/{id}', + 'verb' => 'DELETE' + ], + ] + ] +); + +$application->registerOCSApi(); diff --git a/apps/federation/backgroundjob/getsharedsecret.php b/apps/federation/backgroundjob/getsharedsecret.php new file mode 100644 index 00000000000..665c6ec6cce --- /dev/null +++ b/apps/federation/backgroundjob/getsharedsecret.php @@ -0,0 +1,155 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\BackgroundJob; + +use OC\BackgroundJob\QueuedJob; +use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; +use OCP\AppFramework\Http; +use OCP\BackgroundJob\IJobList; +use OCP\Http\Client\IClient; +use OCP\ILogger; +use OCP\IURLGenerator; + +/** + * Class GetSharedSecret + * + * request shared secret from remote ownCloud + * + * @package OCA\Federation\Backgroundjob + */ +class GetSharedSecret extends QueuedJob{ + + /** @var IClient */ + private $httpClient; + + /** @var IJobList */ + private $jobList; + + /** @var IURLGenerator */ + private $urlGenerator; + + /** @var TrustedServers */ + private $trustedServers; + + /** @var ILogger */ + private $logger; + + private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json'; + + /** + * RequestSharedSecret constructor. + * + * @param IClient $httpClient + * @param IURLGenerator $urlGenerator + * @param IJobList $jobList + * @param TrustedServers $trustedServers + * @param ILogger $logger + */ + public function __construct( + IClient $httpClient = null, + IURLGenerator $urlGenerator = null, + IJobList $jobList = null, + TrustedServers $trustedServers = null, + ILogger $logger = null + ) { + $this->logger = $logger ? $logger : \OC::$server->getLogger(); + $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient(); + $this->jobList = $jobList ? $jobList : \OC::$server->getJobList(); + $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator(); + if ($trustedServers) { + $this->trustedServers = $trustedServers; + } else { + $this->trustedServers = new TrustedServers( + new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')), + \OC::$server->getHTTPClientService(), + \OC::$server->getLogger(), + $this->jobList, + \OC::$server->getSecureRandom() + ); + } + } + + /** + * run the job, then remove it from the joblist + * + * @param JobList $jobList + * @param ILogger $logger + */ + public function execute($jobList, ILogger $logger = null) { + $jobList->remove($this, $this->argument); + $target = $this->argument['url']; + // only execute if target is still in the list of trusted domains + if ($this->trustedServers->isTrustedServer($target)) { + parent::execute($jobList, $logger); + } + } + + protected function run($argument) { + $target = $argument['url']; + $source = $this->urlGenerator->getAbsoluteURL('/'); + $source = rtrim($source, '/'); + $token = $argument['token']; + + $result = $this->httpClient->get( + $target . $this->endPoint, + [ + 'query' => + [ + 'url' => $source, + 'token' => $token + ], + 'timeout' => 3, + 'connect_timeout' => 3, + ] + ); + + $status = $result->getStatusCode(); + + // if we received a unexpected response we try again later + if ( + $status !== Http::STATUS_OK + && $status !== Http::STATUS_FORBIDDEN + ) { + $this->jobList->add( + 'OCA\Federation\Backgroundjob\RequestSharedSecret', + $argument + ); + } elseif ($status === Http::STATUS_OK) { + $body = $result->getBody(); + $result = json_decode($body, true); + if (isset($result['ocs']['data']['sharedSecret'])) { + $this->trustedServers->addSharedSecret( + $target, + $result['ocs']['data']['sharedSecret'] + ); + } else { + $this->logger->error( + 'remote server "' . $target . '"" does not return a valid shared secret', + ['app' => 'federation'] + ); + $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE); + } + } + } +} diff --git a/apps/federation/backgroundjob/requestsharedsecret.php b/apps/federation/backgroundjob/requestsharedsecret.php new file mode 100644 index 00000000000..b61026a4d66 --- /dev/null +++ b/apps/federation/backgroundjob/requestsharedsecret.php @@ -0,0 +1,134 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\BackgroundJob; + + +use OC\BackgroundJob\QueuedJob; +use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; +use OCP\AppFramework\Http; +use OCP\BackgroundJob\IJobList; +use OCP\Http\Client\IClient; +use OCP\ILogger; +use OCP\IURLGenerator; + +/** + * Class RequestSharedSecret + * + * Ask remote ownCloud to request a sharedSecret from this server + * + * @package OCA\Federation\Backgroundjob + */ +class RequestSharedSecret extends QueuedJob { + + /** @var IClient */ + private $httpClient; + + /** @var IJobList */ + private $jobList; + + /** @var IURLGenerator */ + private $urlGenerator; + + private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json'; + + /** + * RequestSharedSecret constructor. + * + * @param IClient $httpClient + * @param IURLGenerator $urlGenerator + * @param IJobList $jobList + * @param TrustedServers $trustedServers + */ + public function __construct( + IClient $httpClient = null, + IURLGenerator $urlGenerator = null, + IJobList $jobList = null, + TrustedServers $trustedServers = null + ) { + $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient(); + $this->jobList = $jobList ? $jobList : \OC::$server->getJobList(); + $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator(); + if ($trustedServers) { + $this->trustedServers = $trustedServers; + } else { + $this->trustedServers = new TrustedServers( + new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')), + \OC::$server->getHTTPClientService(), + \OC::$server->getLogger(), + $this->jobList, + \OC::$server->getSecureRandom() + ); + } + } + + + /** + * run the job, then remove it from the joblist + * + * @param JobList $jobList + * @param ILogger $logger + */ + public function execute($jobList, ILogger $logger = null) { + $jobList->remove($this, $this->argument); + $target = $this->argument['url']; + // only execute if target is still in the list of trusted domains + if ($this->trustedServers->isTrustedServer($target)) { + parent::execute($jobList, $logger); + } + } + + protected function run($argument) { + + $target = $argument['url']; + $source = $this->urlGenerator->getAbsoluteURL('/'); + $source = rtrim($source, '/'); + $token = $argument['token']; + + $result = $this->httpClient->post( + $target . $this->endPoint, + [ + 'body' => [ + 'url' => $source, + 'token' => $token, + ], + 'timeout' => 3, + 'connect_timeout' => 3, + ] + ); + + $status = $result->getStatusCode(); + + // if we received a unexpected response we try again later + if ( + $status !== Http::STATUS_OK + && $status !== Http::STATUS_FORBIDDEN + ) { + $this->jobList->add( + 'OCA\Federation\BackgroundJob\RequestSharedSecret', + $argument + ); + } + + } +} diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index 1100875cc23..58cf0f7f3b9 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -23,10 +23,19 @@ namespace OCA\Federation; +use OC\Files\Filesystem; use OC\HintException; use OCP\IDBConnection; use OCP\IL10N; +/** + * Class DbHandler + * + * handles all database calls for the federation app + * + * @group DB + * @package OCA\Federation + */ class DbHandler { /** @var IDBConnection */ @@ -53,12 +62,12 @@ class DbHandler { /** * add server to the list of trusted ownCloud servers * - * @param $url + * @param string $url * @return int * @throws HintException */ - public function add($url) { - $hash = md5($url); + public function addServer($url) { + $hash = $this->hash($url); $query = $this->connection->getQueryBuilder(); $query->insert($this->dbTable) ->values( @@ -73,14 +82,7 @@ class DbHandler { $result = $query->execute(); if ($result) { - $id = $this->connection->lastInsertId(); - // Fallback, if lastInterId() doesn't work we need to perform a select - // to get the ID (seems to happen sometimes on Oracle) - if (!$id) { - $server = $this->get($url); - $id = $server['id']; - } - return $id; + return $this->connection->lastInsertId($this->dbTable); } else { $message = 'Internal failure, Could not add ownCloud as trusted server: ' . $url; $message_t = $this->l->t('Could not add server'); @@ -93,7 +95,7 @@ class DbHandler { * * @param int $id */ - public function remove($id) { + public function removeServer($id) { $query = $this->connection->getQueryBuilder(); $query->delete($this->dbTable) ->where($query->expr()->eq('id', $query->createParameter('id'))) @@ -101,27 +103,12 @@ class DbHandler { $query->execute(); } - /** - * get trusted server from database - * - * @param $url - * @return mixed - */ - public function get($url) { - $query = $this->connection->getQueryBuilder(); - $query->select('url', 'id')->from($this->dbTable) - ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) - ->setParameter('url_hash', md5($url)); - - return $query->execute()->fetch(); - } - /** * get all trusted servers * * @return array */ - public function getAll() { + public function getAllServer() { $query = $this->connection->getQueryBuilder(); $query->select('url', 'id')->from($this->dbTable); $result = $query->execute()->fetchAll(); @@ -134,14 +121,149 @@ class DbHandler { * @param string $url * @return bool */ - public function exists($url) { + public function serverExists($url) { + $hash = $this->hash($url); $query = $this->connection->getQueryBuilder(); $query->select('url')->from($this->dbTable) ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) - ->setParameter('url_hash', md5($url)); + ->setParameter('url_hash', $hash); $result = $query->execute()->fetchAll(); return !empty($result); } + /** + * write token to database. Token is used to exchange the secret + * + * @param string $url + * @param string $token + */ + public function addToken($url, $token) { + $hash = $this->hash($url); + $query = $this->connection->getQueryBuilder(); + $query->update($this->dbTable) + ->set('token', $query->createParameter('token')) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', $hash) + ->setParameter('token', $token); + $query->execute(); + } + + /** + * get token stored in database + * + * @param string $url + * @return string + */ + public function getToken($url) { + $hash = $this->hash($url); + $query = $this->connection->getQueryBuilder(); + $query->select('token')->from($this->dbTable) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', $hash); + + $result = $query->execute()->fetch(); + return $result['token']; + } + + /** + * add shared Secret to database + * + * @param string $url + * @param string $sharedSecret + */ + public function addSharedSecret($url, $sharedSecret) { + $hash = $this->hash($url); + $query = $this->connection->getQueryBuilder(); + $query->update($this->dbTable) + ->set('shared_secret', $query->createParameter('sharedSecret')) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', $hash) + ->setParameter('sharedSecret', $sharedSecret); + $query->execute(); + } + + /** + * get shared secret from database + * + * @param string $url + * @return string + */ + public function getSharedSecret($url) { + $hash = $this->hash($url); + $query = $this->connection->getQueryBuilder(); + $query->select('shared_secret')->from($this->dbTable) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', $hash); + + $result = $query->execute()->fetch(); + return $result['shared_secret']; + } + + /** + * set server status + * + * @param string $url + * @param int $status + */ + public function setServerStatus($url, $status) { + $hash = $this->hash($url); + $query = $this->connection->getQueryBuilder(); + $query->update($this->dbTable) + ->set('status', $query->createParameter('status')) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', $hash) + ->setParameter('status', $status); + $query->execute(); + } + + /** + * get server status + * + * @param string $url + * @return int + */ + public function getServerStatus($url) { + $hash = $this->hash($url); + $query = $this->connection->getQueryBuilder(); + $query->select('status')->from($this->dbTable) + ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) + ->setParameter('url_hash', $hash); + + $result = $query->execute()->fetch(); + return $result['status']; + } + + /** + * create hash from URL + * + * @param string $url + * @return string + */ + protected function hash($url) { + $normalized = $this->normalizeUrl($url); + return md5($normalized); + } + + /** + * normalize URL, used to create the md5 hash + * + * @param string $url + * @return string + */ + protected function normalizeUrl($url) { + $normalized = $url; + + if (strpos($url, 'https://') === 0) { + $normalized = substr($url, strlen('https://')); + } else if (strpos($url, 'http://') === 0) { + $normalized = substr($url, strlen('http://')); + } + + $normalized = Filesystem::normalizePath($normalized); + $normalized = trim($normalized, '/'); + + return $normalized; + } + } diff --git a/apps/federation/lib/trustedservers.php b/apps/federation/lib/trustedservers.php index bf31277b2a8..f3ac6e24fc6 100644 --- a/apps/federation/lib/trustedservers.php +++ b/apps/federation/lib/trustedservers.php @@ -22,15 +22,21 @@ namespace OCA\Federation; - -use OC\Files\Filesystem; use OCP\AppFramework\Http; +use OCP\BackgroundJob\IJobList; use OCP\Http\Client\IClientService; -use OCP\IDBConnection; use OCP\ILogger; +use OCP\Security\ISecureRandom; class TrustedServers { + /** after a user list was exchanged at least once successfully */ + const STATUS_OK = 1; + /** waiting for shared secret or initial user list exchange */ + const STATUS_PENDING = 2; + /** something went wrong, misconfigured server, software bug,... user interaction needed */ + const STATUS_FAILURE = 3; + /** @var dbHandler */ private $dbHandler; @@ -40,21 +46,31 @@ class TrustedServers { /** @var ILogger */ private $logger; - private $dbTable = 'trusted_servers'; + /** @var IJobList */ + private $jobList; + + /** @var ISecureRandom */ + private $secureRandom; /** * @param DbHandler $dbHandler * @param IClientService $httpClientService * @param ILogger $logger + * @param IJobList $jobList + * @param ISecureRandom $secureRandom */ public function __construct( DbHandler $dbHandler, IClientService $httpClientService, - ILogger $logger + ILogger $logger, + IJobList $jobList, + ISecureRandom $secureRandom ) { $this->dbHandler = $dbHandler; $this->httpClientService = $httpClientService; $this->logger = $logger; + $this->jobList = $jobList; + $this->secureRandom = $secureRandom; } /** @@ -64,7 +80,41 @@ class TrustedServers { * @return int server id */ public function addServer($url) { - return $this->dbHandler->add($this->normalizeUrl($url)); + $url = $this->updateProtocol($url); + $result = $this->dbHandler->addServer($url); + if ($result) { + $token = $this->secureRandom->getMediumStrengthGenerator()->generate(16); + $this->dbHandler->addToken($url, $token); + $this->jobList->add( + 'OCA\Federation\BackgroundJob\RequestSharedSecret', + [ + 'url' => $url, + 'token' => $token + ] + ); + } + + return $result; + } + + /** + * get shared secret for the given server + * + * @param string $url + * @return string + */ + public function getSharedSecret($url) { + return $this->dbHandler->getSharedSecret($url); + } + + /** + * add shared secret for the given server + * + * @param string $url + * @param $sharedSecret + */ + public function addSharedSecret($url, $sharedSecret) { + $this->dbHandler->addSharedSecret($url, $sharedSecret); } /** @@ -73,7 +123,7 @@ class TrustedServers { * @param int $id */ public function removeServer($id) { - $this->dbHandler->remove($id); + $this->dbHandler->removeServer($id); } /** @@ -82,7 +132,7 @@ class TrustedServers { * @return array */ public function getServers() { - return $this->dbHandler->getAll(); + return $this->dbHandler->getAllServer(); } /** @@ -92,7 +142,25 @@ class TrustedServers { * @return bool */ public function isTrustedServer($url) { - return $this->dbHandler->exists($this->normalizeUrl($url)); + return $this->dbHandler->serverExists($url); + } + + /** + * set server status + * + * @param string $url + * @param int $status + */ + public function setServerStatus($url, $status) { + $this->dbHandler->setServerStatus($url, $status); + } + + /** + * @param string $url + * @return int + */ + public function getServerStatus($url) { + return $this->dbHandler->getServerStatus($url); } /** @@ -137,24 +205,21 @@ class TrustedServers { } /** - * normalize URL + * check if the URL contain a protocol, if not add https * * @param string $url * @return string */ - protected function normalizeUrl($url) { + protected function updateProtocol($url) { + if ( + strpos($url, 'https://') === 0 + || strpos($url, 'http://') === 0 + ) { - $normalized = $url; + return $url; - if (strpos($url, 'https://') === 0) { - $normalized = substr($url, strlen('https://')); - } else if (strpos($url, 'http://') === 0) { - $normalized = substr($url, strlen('http://')); } - $normalized = Filesystem::normalizePath($normalized); - $normalized = trim($normalized, '/'); - - return $normalized; + return 'https://' . $url; } } diff --git a/apps/federation/settings/settings-admin.php b/apps/federation/settings/settings-admin.php index ea71475d619..c160b7ee825 100644 --- a/apps/federation/settings/settings-admin.php +++ b/apps/federation/settings/settings-admin.php @@ -31,7 +31,9 @@ $dbHandler = new \OCA\Federation\DbHandler( $trustedServers = new \OCA\Federation\TrustedServers( $dbHandler, \OC::$server->getHTTPClientService(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getJobList(), + \OC::$server->getSecureRandom() ); $template->assign('trustedServers', $trustedServers->getServers()); diff --git a/apps/federation/tests/api/ocsauthapitest.php b/apps/federation/tests/api/ocsauthapitest.php new file mode 100644 index 00000000000..a334686c24e --- /dev/null +++ b/apps/federation/tests/api/ocsauthapitest.php @@ -0,0 +1,184 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\API; + + +use OC\BackgroundJob\JobList; +use OCA\Federation\API\OCSAuthAPI; +use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; +use OCP\AppFramework\Http; +use OCP\IRequest; +use OCP\Security\ISecureRandom; +use Test\TestCase; + +class OCSAuthAPITest extends TestCase { + + /** @var \PHPUnit_Framework_MockObject_MockObject | IRequest */ + private $request; + + /** @var \PHPUnit_Framework_MockObject_MockObject | ISecureRandom */ + private $secureRandom; + + /** @var \PHPUnit_Framework_MockObject_MockObject | JobList */ + private $jobList; + + /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers */ + private $trustedServers; + + /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */ + private $dbHandler; + + /** @var OCSAuthApi */ + private $ocsAuthApi; + + public function setUp() { + parent::setUp(); + + $this->request = $this->getMock('OCP\IRequest'); + $this->secureRandom = $this->getMock('OCP\Security\ISecureRandom'); + $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->disableOriginalConstructor()->getMock(); + $this->dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler') + ->disableOriginalConstructor()->getMock(); + $this->jobList = $this->getMockBuilder('OC\BackgroundJob\JobList') + ->disableOriginalConstructor()->getMock(); + + $this->ocsAuthApi = new OCSAuthAPI( + $this->request, + $this->secureRandom, + $this->jobList, + $this->trustedServers, + $this->dbHandler + ); + + } + + /** + * @dataProvider dataTestRequestSharedSecret + * + * @param string $token + * @param string $localToken + * @param bool $isTrustedServer + * @param int $expected + */ + public function testRequestSharedSecret($token, $localToken, $isTrustedServer, $expected) { + + $url = 'url'; + + $this->request->expects($this->at(0))->method('getParam')->with('url')->willReturn($url); + $this->request->expects($this->at(1))->method('getParam')->with('token')->willReturn($token); + $this->trustedServers + ->expects($this->once()) + ->method('isTrustedServer')->with($url)->willReturn($isTrustedServer); + $this->dbHandler->expects($this->any()) + ->method('getToken')->with($url)->willReturn($localToken); + + if ($expected === Http::STATUS_OK) { + $this->jobList->expects($this->once())->method('add') + ->with('OCA\Federation\BackgroundJob\GetSharedSecret', ['url' => $url, 'token' => $token]); + } else { + $this->jobList->expects($this->never())->method('add'); + } + + $result = $this->ocsAuthApi->requestSharedSecret(); + $this->assertSame($expected, $result->getStatusCode()); + } + + public function dataTestRequestSharedSecret() { + return [ + ['token2', 'token1', true, Http::STATUS_OK], + ['token1', 'token2', false, Http::STATUS_FORBIDDEN], + ['token1', 'token2', true, Http::STATUS_FORBIDDEN], + ]; + } + + /** + * @dataProvider dataTestGetSharedSecret + * + * @param bool $isTrustedServer + * @param bool $isValidToken + * @param int $expected + */ + public function testGetSharedSecret($isTrustedServer, $isValidToken, $expected) { + + $url = 'url'; + $token = 'token'; + + $this->request->expects($this->at(0))->method('getParam')->with('url')->willReturn($url); + $this->request->expects($this->at(1))->method('getParam')->with('token')->willReturn($token); + + /** @var OCSAuthAPI | \PHPUnit_Framework_MockObject_MockObject $ocsAuthApi */ + $ocsAuthApi = $this->getMockBuilder('OCA\Federation\API\OCSAuthAPI') + ->setConstructorArgs( + [ + $this->request, + $this->secureRandom, + $this->jobList, + $this->trustedServers, + $this->dbHandler + ] + )->setMethods(['isValidToken'])->getMock(); + + $this->trustedServers + ->expects($this->any()) + ->method('isTrustedServer')->with($url)->willReturn($isTrustedServer); + $ocsAuthApi->expects($this->any()) + ->method('isValidToken')->with($url, $token)->willReturn($isValidToken); + + if($expected === Http::STATUS_OK) { + $this->secureRandom->expects($this->once())->method('getMediumStrengthGenerator') + ->willReturn($this->secureRandom); + $this->secureRandom->expects($this->once())->method('generate')->with(32) + ->willReturn('secret'); + $this->trustedServers->expects($this->once()) + ->method('addSharedSecret')->willReturn($url, 'secret'); + $this->dbHandler->expects($this->once()) + ->method('addToken')->with($url, ''); + } else { + $this->secureRandom->expects($this->never())->method('getMediumStrengthGenerator'); + $this->secureRandom->expects($this->never())->method('generate'); + $this->trustedServers->expects($this->never())->method('addSharedSecret'); + $this->dbHandler->expects($this->never())->method('addToken'); + } + + $result = $ocsAuthApi->getSharedSecret(); + + $this->assertSame($expected, $result->getStatusCode()); + + if ($expected === Http::STATUS_OK) { + $data = $result->getData(); + $this->assertSame('secret', $data['sharedSecret']); + } + } + + public function dataTestGetSharedSecret() { + return [ + [true, true, Http::STATUS_OK], + [false, true, Http::STATUS_FORBIDDEN], + [true, false, Http::STATUS_FORBIDDEN], + [false, false, Http::STATUS_FORBIDDEN], + ]; + } + +} diff --git a/apps/federation/tests/lib/dbhandlertest.php b/apps/federation/tests/lib/dbhandlertest.php index 202199d2b5b..50bb9a73d92 100644 --- a/apps/federation/tests/lib/dbhandlertest.php +++ b/apps/federation/tests/lib/dbhandlertest.php @@ -27,6 +27,9 @@ use OCA\Federation\DbHandler; use OCP\IDBConnection; use Test\TestCase; +/** + * @group DB + */ class DbHandlerTest extends TestCase { /** @var DbHandler */ @@ -63,8 +66,8 @@ class DbHandlerTest extends TestCase { $query->execute(); } - public function testAdd() { - $id = $this->dbHandler->add('server1'); + public function testAddServer() { + $id = $this->dbHandler->addServer('server1'); $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); $result = $query->execute()->fetchAll(); @@ -74,8 +77,8 @@ class DbHandlerTest extends TestCase { } public function testRemove() { - $id1 = $this->dbHandler->add('server1'); - $id2 = $this->dbHandler->add('server2'); + $id1 = $this->dbHandler->addServer('server1'); + $id2 = $this->dbHandler->addServer('server2'); $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); $result = $query->execute()->fetchAll(); @@ -85,7 +88,7 @@ class DbHandlerTest extends TestCase { $this->assertSame($id1, $result[0]['id']); $this->assertSame($id2, $result[1]['id']); - $this->dbHandler->remove($id2); + $this->dbHandler->removeServer($id2); $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); $result = $query->execute()->fetchAll(); $this->assertSame(1, count($result)); @@ -94,10 +97,10 @@ class DbHandlerTest extends TestCase { } public function testGetAll() { - $id1 = $this->dbHandler->add('server1'); - $id2 = $this->dbHandler->add('server2'); + $id1 = $this->dbHandler->addServer('server1'); + $id2 = $this->dbHandler->addServer('server2'); - $result = $this->dbHandler->getAll(); + $result = $this->dbHandler->getAllServer(); $this->assertSame(2, count($result)); $this->assertSame('server1', $result[0]['url']); $this->assertSame('server2', $result[1]['url']); @@ -113,9 +116,9 @@ class DbHandlerTest extends TestCase { * @param bool $expected */ public function testExists($serverInTable, $checkForServer, $expected) { - $this->dbHandler->add($serverInTable); + $this->dbHandler->addServer($serverInTable); $this->assertSame($expected, - $this->dbHandler->exists($checkForServer) + $this->dbHandler->serverExists($checkForServer) ); } @@ -127,4 +130,26 @@ class DbHandlerTest extends TestCase { ]; } + /** + * @dataProvider dataTestNormalizeUrl + * + * @param string $url + * @param string $expected + */ + public function testNormalizeUrl($url, $expected) { + $this->assertSame($expected, + $this->invokePrivate($this->dbHandler, 'normalizeUrl', [$url]) + ); + } + + public function dataTestNormalizeUrl() { + return [ + ['owncloud.org', 'owncloud.org'], + ['http://owncloud.org', 'owncloud.org'], + ['https://owncloud.org', 'owncloud.org'], + ['https://owncloud.org//mycloud', 'owncloud.org/mycloud'], + ['https://owncloud.org/mycloud/', 'owncloud.org/mycloud'], + ]; + } + } diff --git a/apps/federation/tests/lib/trustedserverstest.php b/apps/federation/tests/lib/trustedserverstest.php index 07aa7531274..dabf353ef21 100644 --- a/apps/federation/tests/lib/trustedserverstest.php +++ b/apps/federation/tests/lib/trustedserverstest.php @@ -25,11 +25,13 @@ namespace OCA\Federation\Tests\lib; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; +use OCP\BackgroundJob\IJobList; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; use OCP\Http\Client\IResponse; -use OCP\IDBConnection; +use OCP\IConfig; use OCP\ILogger; +use OCP\Security\ISecureRandom; use Test\TestCase; class TrustedServersTest extends TestCase { @@ -52,6 +54,15 @@ class TrustedServersTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */ private $logger; + /** @var \PHPUnit_Framework_MockObject_MockObject | IJobList */ + private $jobList; + + /** @var \PHPUnit_Framework_MockObject_MockObject | ISecureRandom */ + private $secureRandom; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IConfig */ + private $config; + public function setUp() { parent::setUp(); @@ -61,45 +72,79 @@ class TrustedServersTest extends TestCase { $this->httpClient = $this->getMock('OCP\Http\Client\IClient'); $this->response = $this->getMock('OCP\Http\Client\IResponse'); $this->logger = $this->getMock('OCP\ILogger'); + $this->jobList = $this->getMock('OCP\BackgroundJob\IJobList'); + $this->secureRandom = $this->getMock('OCP\Security\ISecureRandom'); + $this->config = $this->getMock('OCP\IConfig'); $this->trustedServers = new TrustedServers( $this->dbHandler, $this->httpClientService, - $this->logger + $this->logger, + $this->jobList, + $this->secureRandom, + $this->config ); } - public function testAddServer() { + /** + * @dataProvider dataTestAddServer + * + * @param bool $success + */ + public function testAddServer($success) { /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') ->setConstructorArgs( [ $this->dbHandler, $this->httpClientService, - $this->logger + $this->logger, + $this->jobList, + $this->secureRandom, + $this->config ] ) - ->setMethods(['normalizeUrl']) + ->setMethods(['normalizeUrl', 'updateProtocol']) ->getMock(); - $trustedServers->expects($this->once())->method('normalizeUrl') - ->with('url')->willReturn('normalized'); - $this->dbHandler->expects($this->once())->method('add')->with('normalized') - ->willReturn(true); + $trustedServers->expects($this->once())->method('updateProtocol') + ->with('url')->willReturn('https://url'); + $this->dbHandler->expects($this->once())->method('addServer')->with('https://url') + ->willReturn($success); + + if ($success) { + $this->secureRandom->expects($this->once())->method('getMediumStrengthGenerator') + ->willReturn($this->secureRandom); + $this->secureRandom->expects($this->once())->method('generate') + ->willReturn('token'); + $this->dbHandler->expects($this->once())->method('addToken')->with('https://url', 'token'); + $this->jobList->expects($this->once())->method('add') + ->with('OCA\Federation\BackgroundJob\RequestSharedSecret', + ['url' => 'https://url', 'token' => 'token']); + } else { + $this->jobList->expects($this->never())->method('add'); + } - $this->assertTrue( + $this->assertSame($success, $trustedServers->addServer('url') ); } + public function dataTestAddServer() { + return [ + [true], + [false] + ]; + } + public function testRemoveServer() { $id = 42; - $this->dbHandler->expects($this->once())->method('remove')->with($id); + $this->dbHandler->expects($this->once())->method('removeServer')->with($id); $this->trustedServers->removeServer($id); } public function testGetServers() { - $this->dbHandler->expects($this->once())->method('getAll')->willReturn(true); + $this->dbHandler->expects($this->once())->method('getAllServer')->willReturn(true); $this->assertTrue( $this->trustedServers->getServers() @@ -108,24 +153,11 @@ class TrustedServersTest extends TestCase { public function testIsTrustedServer() { - /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ - $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') - ->setConstructorArgs( - [ - $this->dbHandler, - $this->httpClientService, - $this->logger - ] - ) - ->setMethods(['normalizeUrl']) - ->getMock(); - $trustedServers->expects($this->once())->method('normalizeUrl') - ->with('url')->willReturn('normalized'); - $this->dbHandler->expects($this->once())->method('exists')->with('normalized') - ->willReturn(true); + $this->dbHandler->expects($this->once())->method('serverExists')->with('url') + ->willReturn(true); $this->assertTrue( - $trustedServers->isTrustedServer('url') + $this->trustedServers->isTrustedServer('url') ); } @@ -146,7 +178,10 @@ class TrustedServersTest extends TestCase { [ $this->dbHandler, $this->httpClientService, - $this->logger + $this->logger, + $this->jobList, + $this->secureRandom, + $this->config ] ) ->setMethods(['checkOwnCloudVersion']) @@ -192,7 +227,7 @@ class TrustedServersTest extends TestCase { ->with('simulated exception', ['app' => 'federation']); $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php') - ->willReturnCallback(function() { + ->willReturnCallback(function () { throw new \Exception('simulated exception'); }); @@ -221,24 +256,22 @@ class TrustedServersTest extends TestCase { } /** - * @dataProvider dataTestNormalizeUrl - * + * @dataProvider dataTestUpdateProtocol * @param string $url * @param string $expected */ - public function testNormalizeUrl($url, $expected) { + public function testUpdateProtocol($url, $expected) { $this->assertSame($expected, - $this->invokePrivate($this->trustedServers, 'normalizeUrl', [$url]) + $this->invokePrivate($this->trustedServers, 'updateProtocol', [$url]) ); } - public function dataTestNormalizeUrl() { + public function dataTestUpdateProtocol() { return [ - ['owncloud.org', 'owncloud.org'], - ['http://owncloud.org', 'owncloud.org'], - ['https://owncloud.org', 'owncloud.org'], - ['https://owncloud.org//mycloud', 'owncloud.org/mycloud'], - ['https://owncloud.org/mycloud/', 'owncloud.org/mycloud'], + ['http://owncloud.org', 'http://owncloud.org'], + ['https://owncloud.org', 'https://owncloud.org'], + ['owncloud.org', 'https://owncloud.org'], + ['httpserver', 'https://httpserver'], ]; } } -- GitLab From c5e41450f6f1fb00acdd84ab9af84f0217025622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 17 Nov 2015 10:17:47 +0100 Subject: [PATCH 096/344] add federation to shipped.json --- core/shipped.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/shipped.json b/core/shipped.json index cd1fca4d9fe..a7466a41aef 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -32,7 +32,8 @@ "user_ldap", "user_shibboleth", "windows_network_drive", - "password_policy" + "password_policy", + "federation" ], "alwaysEnabled": [ "files", -- GitLab From 97c60fd21794a6a0a56dc69ba8b77ab93b5d212c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 18 Nov 2015 11:49:10 +0100 Subject: [PATCH 097/344] change 'cronstatus' to 'status' so that it can be used in other apps too --- settings/css/settings.css | 4 ++-- settings/templates/admin.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/settings/css/settings.css b/settings/css/settings.css index 60ba805d3ca..5a1d864734b 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -412,13 +412,13 @@ table.grid td.date{ .cronlog { margin-left: 10px; } -.cronstatus { +.status { display: inline-block; height: 16px; width: 16px; vertical-align: text-bottom; } -.cronstatus.success { +.status.success { border-radius: 50%; } diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 24af4964248..0721c0e0afb 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -290,18 +290,18 @@ if ($_['cronErrors']) { $relative_time = relative_modified_date($_['lastcron']); $absolute_time = OC_Util::formatDate($_['lastcron']); if (time() - $_['lastcron'] <= 3600): ?> - + t("Last cron job execution: %s.", [$relative_time]));?> - + t("Last cron job execution: %s. Something seems wrong.", [$relative_time]));?> - + t("Cron was not executed yet!")); endif; ?>

    -- GitLab From 8f55b1a27d97f24751542b6dc44a89eb03387a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 18 Nov 2015 13:38:03 +0100 Subject: [PATCH 098/344] add status to server list --- apps/federation/css/settings-admin.css | 6 ++++-- apps/federation/js/settings-admin.js | 5 ++++- apps/federation/lib/dbhandler.php | 2 +- apps/federation/templates/settings-admin.php | 11 ++++++++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/federation/css/settings-admin.css b/apps/federation/css/settings-admin.css index 7dbc949270f..55b1dd64d15 100644 --- a/apps/federation/css/settings-admin.css +++ b/apps/federation/css/settings-admin.css @@ -19,6 +19,8 @@ #listOfTrustedServers li:hover { cursor: pointer; - background: url(../../../core/img/actions/delete.svg) no-repeat left center; - padding-left: 20px; +} + +#listOfTrustedServers .status { + margin-right: 10px; } diff --git a/apps/federation/js/settings-admin.js b/apps/federation/js/settings-admin.js index a1f02a09efe..1bc7a8cc0aa 100644 --- a/apps/federation/js/settings-admin.js +++ b/apps/federation/js/settings-admin.js @@ -40,7 +40,10 @@ $(document).ready(function () { ).done(function (data) { $('#serverUrl').attr('value', ''); $('ul#listOfTrustedServers').prepend( - $('
  • ').attr('id', data.id).text(data.url) + $('
  • ') + .attr('id', data.id) + .attr('class', 'icon-delete') + .html('' + data.url) ); OC.msg.finishedSuccess('#ocFederationAddServer .msg', data.message); }) diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index 58cf0f7f3b9..2b57dd75419 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -110,7 +110,7 @@ class DbHandler { */ public function getAllServer() { $query = $this->connection->getQueryBuilder(); - $query->select('url', 'id')->from($this->dbTable); + $query->select('url', 'id', 'status')->from($this->dbTable); $result = $query->execute()->fetchAll(); return $result; } diff --git a/apps/federation/templates/settings-admin.php b/apps/federation/templates/settings-admin.php index faa1e393158..f9087137d56 100644 --- a/apps/federation/templates/settings-admin.php +++ b/apps/federation/templates/settings-admin.php @@ -1,5 +1,7 @@
      -
    • +
    • + + + + + + +
    • -- GitLab From 2754afc0747950591b3ddca37248d363c6ab64f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 18 Nov 2015 15:07:41 +0100 Subject: [PATCH 099/344] add option to auto add servers to the list of trusted servers once a federated share was created and accepted successfully --- apps/federation/appinfo/application.php | 3 +- apps/federation/appinfo/routes.php | 5 +++ .../backgroundjob/getsharedsecret.php | 3 +- .../backgroundjob/requestsharedsecret.php | 3 +- .../controller/settingscontroller.php | 11 +++++++ apps/federation/js/settings-admin.js | 9 ++++++ apps/federation/lib/trustedservers.php | 31 ++++++++++++++++++- apps/federation/settings/settings-admin.php | 4 ++- apps/federation/templates/settings-admin.php | 6 ++-- 9 files changed, 67 insertions(+), 8 deletions(-) diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php index e91506a30bd..72a30f9ae0a 100644 --- a/apps/federation/appinfo/application.php +++ b/apps/federation/appinfo/application.php @@ -73,7 +73,8 @@ class Application extends \OCP\AppFramework\App { \OC::$server->getHTTPClientService(), \OC::$server->getLogger(), \OC::$server->getJobList(), - \OC::$server->getSecureRandom() + \OC::$server->getSecureRandom(), + \OC::$server->getConfig() ); }); diff --git a/apps/federation/appinfo/routes.php b/apps/federation/appinfo/routes.php index f45db43e4e7..8c1629a4fc6 100644 --- a/apps/federation/appinfo/routes.php +++ b/apps/federation/appinfo/routes.php @@ -35,6 +35,11 @@ $application->registerRoutes( 'url' => '/trusted-servers/{id}', 'verb' => 'DELETE' ], + [ + 'name' => 'Settings#autoAddServers', + 'url' => '/auto-add-servers', + 'verb' => 'POST' + ], ] ] ); diff --git a/apps/federation/backgroundjob/getsharedsecret.php b/apps/federation/backgroundjob/getsharedsecret.php index 665c6ec6cce..3e8597cd78b 100644 --- a/apps/federation/backgroundjob/getsharedsecret.php +++ b/apps/federation/backgroundjob/getsharedsecret.php @@ -85,7 +85,8 @@ class GetSharedSecret extends QueuedJob{ \OC::$server->getHTTPClientService(), \OC::$server->getLogger(), $this->jobList, - \OC::$server->getSecureRandom() + \OC::$server->getSecureRandom(), + \OC::$server->getConfig() ); } } diff --git a/apps/federation/backgroundjob/requestsharedsecret.php b/apps/federation/backgroundjob/requestsharedsecret.php index b61026a4d66..b73b620b4b7 100644 --- a/apps/federation/backgroundjob/requestsharedsecret.php +++ b/apps/federation/backgroundjob/requestsharedsecret.php @@ -77,7 +77,8 @@ class RequestSharedSecret extends QueuedJob { \OC::$server->getHTTPClientService(), \OC::$server->getLogger(), $this->jobList, - \OC::$server->getSecureRandom() + \OC::$server->getSecureRandom(), + \OC::$server->getConfig() ); } } diff --git a/apps/federation/controller/settingscontroller.php b/apps/federation/controller/settingscontroller.php index 8d522328120..2e28cd60cfa 100644 --- a/apps/federation/controller/settingscontroller.php +++ b/apps/federation/controller/settingscontroller.php @@ -26,6 +26,7 @@ use OCA\Federation\TrustedServers; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; @@ -86,6 +87,16 @@ class SettingsController extends Controller { return new DataResponse(); } + /** + * enable/disable to automatically add servers to the list of trusted servers + * once a federated share was created and accepted successfully + * + * @param bool $autoAddServers + */ + public function autoAddServers($autoAddServers) { + $this->trustedServers->setAutoAddServers($autoAddServers); + } + /** * check if the server should be added to the list of trusted servers or not * diff --git a/apps/federation/js/settings-admin.js b/apps/federation/js/settings-admin.js index 1bc7a8cc0aa..7d531b39d8c 100644 --- a/apps/federation/js/settings-admin.js +++ b/apps/federation/js/settings-admin.js @@ -70,4 +70,13 @@ $(document).ready(function () { }); + $("#ocFederationSettings #autoAddServers").change(function() { + $.post( + OC.generateUrl('/apps/federation/auto-add-servers'), + { + autoAddServers: $(this).is(":checked") + } + ); + }); + }); diff --git a/apps/federation/lib/trustedservers.php b/apps/federation/lib/trustedservers.php index f3ac6e24fc6..96a29178076 100644 --- a/apps/federation/lib/trustedservers.php +++ b/apps/federation/lib/trustedservers.php @@ -25,6 +25,7 @@ namespace OCA\Federation; use OCP\AppFramework\Http; use OCP\BackgroundJob\IJobList; use OCP\Http\Client\IClientService; +use OCP\IConfig; use OCP\ILogger; use OCP\Security\ISecureRandom; @@ -52,25 +53,31 @@ class TrustedServers { /** @var ISecureRandom */ private $secureRandom; + /** @var IConfig */ + private $config; + /** * @param DbHandler $dbHandler * @param IClientService $httpClientService * @param ILogger $logger * @param IJobList $jobList * @param ISecureRandom $secureRandom + * @param IConfig $config */ public function __construct( DbHandler $dbHandler, IClientService $httpClientService, ILogger $logger, IJobList $jobList, - ISecureRandom $secureRandom + ISecureRandom $secureRandom, + IConfig $config ) { $this->dbHandler = $dbHandler; $this->httpClientService = $httpClientService; $this->logger = $logger; $this->jobList = $jobList; $this->secureRandom = $secureRandom; + $this->config = $config; } /** @@ -97,6 +104,28 @@ class TrustedServers { return $result; } + /** + * enable/disable to automatically add servers to the list of trusted servers + * once a federated share was created and accepted successfully + * + * @param bool $status + */ + public function setAutoAddServers($status) { + $value = $status ? '1' : '0'; + $this->config->setAppValue('federation', 'autoAddServers', $value); + } + + /** + * return if we automatically add servers to the list of trusted servers + * once a federated share was created and accepted successfully + * + * @return bool + */ + public function getAutoAddServers() { + $value = $this->config->getAppValue('federation', 'autoAddServers', '1'); + return $value === '1'; + } + /** * get shared secret for the given server * diff --git a/apps/federation/settings/settings-admin.php b/apps/federation/settings/settings-admin.php index c160b7ee825..76ae0c3b6e0 100644 --- a/apps/federation/settings/settings-admin.php +++ b/apps/federation/settings/settings-admin.php @@ -33,9 +33,11 @@ $trustedServers = new \OCA\Federation\TrustedServers( \OC::$server->getHTTPClientService(), \OC::$server->getLogger(), \OC::$server->getJobList(), - \OC::$server->getSecureRandom() + \OC::$server->getSecureRandom(), + \OC::$server->getConfig() ); $template->assign('trustedServers', $trustedServers->getServers()); +$template->assign('autoAddServers', $trustedServers->getAutoAddServers()); return $template->fetchPage(); diff --git a/apps/federation/templates/settings-admin.php b/apps/federation/templates/settings-admin.php index f9087137d56..854bb744179 100644 --- a/apps/federation/templates/settings-admin.php +++ b/apps/federation/templates/settings-admin.php @@ -10,9 +10,9 @@ style('federation', 'settings-admin')

      t('Federation')); ?>

      t('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.')); ?> -

      - - +

      + /> +

      Trusted ownCloud Servers

      -- GitLab From 6f7aa3392f4ec47d03164a9732842ec034aeae48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 19 Nov 2015 11:48:21 +0100 Subject: [PATCH 100/344] make sure that both server don't try to exchange the shared secret in parallel --- apps/federation/api/ocsauthapi.php | 9 ++++ .../backgroundjob/getsharedsecret.php | 54 ++++++++++++------- .../backgroundjob/requestsharedsecret.php | 48 ++++++++++++----- 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/apps/federation/api/ocsauthapi.php b/apps/federation/api/ocsauthapi.php index 7965e6f2140..3279ae1dd7b 100644 --- a/apps/federation/api/ocsauthapi.php +++ b/apps/federation/api/ocsauthapi.php @@ -91,6 +91,13 @@ class OCSAuthAPI { return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN); } + // if both server initiated the exchange of the shared secret the greater + // token wins + $localToken = $this->dbHandler->getToken($url); + if (strcmp($localToken, $token) > 0) { + return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN); + } + $this->jobList->add( 'OCA\Federation\BackgroundJob\GetSharedSecret', [ @@ -123,6 +130,8 @@ class OCSAuthAPI { $sharedSecret = $this->secureRandom->getMediumStrengthGenerator()->generate(32); $this->trustedServers->addSharedSecret($url, $sharedSecret); + // reset token after the exchange of the shared secret was successful + $this->dbHandler->addToken($url, ''); return new \OC_OCS_Result(['sharedSecret' => $sharedSecret], Http::STATUS_OK); diff --git a/apps/federation/backgroundjob/getsharedsecret.php b/apps/federation/backgroundjob/getsharedsecret.php index 3e8597cd78b..dd095ed117a 100644 --- a/apps/federation/backgroundjob/getsharedsecret.php +++ b/apps/federation/backgroundjob/getsharedsecret.php @@ -22,6 +22,7 @@ namespace OCA\Federation\BackgroundJob; +use GuzzleHttp\Exception\ClientException; use OC\BackgroundJob\QueuedJob; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; @@ -52,6 +53,9 @@ class GetSharedSecret extends QueuedJob{ /** @var TrustedServers */ private $trustedServers; + /** @var DbHandler */ + private $dbHandler; + /** @var ILogger */ private $logger; @@ -65,23 +69,26 @@ class GetSharedSecret extends QueuedJob{ * @param IJobList $jobList * @param TrustedServers $trustedServers * @param ILogger $logger + * @param DbHandler $dbHandler */ public function __construct( IClient $httpClient = null, IURLGenerator $urlGenerator = null, IJobList $jobList = null, TrustedServers $trustedServers = null, - ILogger $logger = null + ILogger $logger = null, + dbHandler $dbHandler = null ) { $this->logger = $logger ? $logger : \OC::$server->getLogger(); $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient(); $this->jobList = $jobList ? $jobList : \OC::$server->getJobList(); $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator(); + $this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')); if ($trustedServers) { $this->trustedServers = $trustedServers; } else { $this->trustedServers = new TrustedServers( - new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')), + $this->dbHandler, \OC::$server->getHTTPClientService(), \OC::$server->getLogger(), $this->jobList, @@ -112,20 +119,25 @@ class GetSharedSecret extends QueuedJob{ $source = rtrim($source, '/'); $token = $argument['token']; - $result = $this->httpClient->get( - $target . $this->endPoint, - [ - 'query' => - [ - 'url' => $source, - 'token' => $token - ], - 'timeout' => 3, - 'connect_timeout' => 3, - ] - ); - - $status = $result->getStatusCode(); + try { + $result = $this->httpClient->get( + $target . $this->endPoint, + [ + 'query' => + [ + 'url' => $source, + 'token' => $token + ], + 'timeout' => 3, + 'connect_timeout' => 3, + ] + ); + + $status = $result->getStatusCode(); + + } catch (ClientException $e) { + $status = $e->getCode(); + } // if we received a unexpected response we try again later if ( @@ -133,10 +145,15 @@ class GetSharedSecret extends QueuedJob{ && $status !== Http::STATUS_FORBIDDEN ) { $this->jobList->add( - 'OCA\Federation\Backgroundjob\RequestSharedSecret', + 'OCA\Federation\Backgroundjob\GetSharedSecret', $argument ); - } elseif ($status === Http::STATUS_OK) { + } else { + // reset token if we received a valid response + $this->dbHandler->addToken($target, ''); + } + + if ($status === Http::STATUS_OK) { $body = $result->getBody(); $result = json_decode($body, true); if (isset($result['ocs']['data']['sharedSecret'])) { @@ -152,5 +169,6 @@ class GetSharedSecret extends QueuedJob{ $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE); } } + } } diff --git a/apps/federation/backgroundjob/requestsharedsecret.php b/apps/federation/backgroundjob/requestsharedsecret.php index b73b620b4b7..c945757818d 100644 --- a/apps/federation/backgroundjob/requestsharedsecret.php +++ b/apps/federation/backgroundjob/requestsharedsecret.php @@ -23,6 +23,7 @@ namespace OCA\Federation\BackgroundJob; +use GuzzleHttp\Exception\ClientException; use OC\BackgroundJob\QueuedJob; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; @@ -50,6 +51,12 @@ class RequestSharedSecret extends QueuedJob { /** @var IURLGenerator */ private $urlGenerator; + /** @var DbHandler */ + private $dbHandler; + + /** @var TrustedServers */ + private $trustedServers; + private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json'; /** @@ -59,21 +66,24 @@ class RequestSharedSecret extends QueuedJob { * @param IURLGenerator $urlGenerator * @param IJobList $jobList * @param TrustedServers $trustedServers + * @param DbHandler $dbHandler */ public function __construct( IClient $httpClient = null, IURLGenerator $urlGenerator = null, IJobList $jobList = null, - TrustedServers $trustedServers = null + TrustedServers $trustedServers = null, + dbHandler $dbHandler = null ) { $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient(); $this->jobList = $jobList ? $jobList : \OC::$server->getJobList(); $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator(); + $this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')); if ($trustedServers) { $this->trustedServers = $trustedServers; } else { $this->trustedServers = new TrustedServers( - new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')), + $this->dbHandler, \OC::$server->getHTTPClientService(), \OC::$server->getLogger(), $this->jobList, @@ -106,19 +116,24 @@ class RequestSharedSecret extends QueuedJob { $source = rtrim($source, '/'); $token = $argument['token']; - $result = $this->httpClient->post( - $target . $this->endPoint, - [ - 'body' => [ - 'url' => $source, - 'token' => $token, - ], - 'timeout' => 3, - 'connect_timeout' => 3, - ] - ); + try { + $result = $this->httpClient->post( + $target . $this->endPoint, + [ + 'body' => [ + 'url' => $source, + 'token' => $token, + ], + 'timeout' => 3, + 'connect_timeout' => 3, + ] + ); - $status = $result->getStatusCode(); + $status = $result->getStatusCode(); + + } catch (ClientException $e) { + $status = $e->getCode(); + } // if we received a unexpected response we try again later if ( @@ -131,5 +146,10 @@ class RequestSharedSecret extends QueuedJob { ); } + if ($status === Http::STATUS_FORBIDDEN) { + // clear token if remote server refuses to ask for shared secret + $this->dbHandler->addToken($target, ''); + } + } } -- GitLab From f6446a64b62e964e043995f6bfeb2118a7dc489a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 19 Nov 2015 17:10:42 +0100 Subject: [PATCH 101/344] fixing OCI and others --- apps/federation/api/ocsauthapi.php | 10 +++++----- apps/federation/appinfo/application.php | 13 ------------- apps/federation/backgroundjob/getsharedsecret.php | 1 + .../backgroundjob/requestsharedsecret.php | 1 + apps/federation/lib/dbhandler.php | 4 ++-- 5 files changed, 9 insertions(+), 20 deletions(-) diff --git a/apps/federation/api/ocsauthapi.php b/apps/federation/api/ocsauthapi.php index 3279ae1dd7b..42d7113820d 100644 --- a/apps/federation/api/ocsauthapi.php +++ b/apps/federation/api/ocsauthapi.php @@ -22,10 +22,10 @@ namespace OCA\Federation\API; -use OC\BackgroundJob\JobList; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; use OCP\AppFramework\Http; +use OCP\BackgroundJob\IJobList; use OCP\IRequest; use OCP\Security\ISecureRandom; use OCP\Security\StringUtils; @@ -45,7 +45,7 @@ class OCSAuthAPI { /** @var ISecureRandom */ private $secureRandom; - /** @var JobList */ + /** @var IJobList */ private $jobList; /** @var TrustedServers */ @@ -55,18 +55,18 @@ class OCSAuthAPI { private $dbHandler; /** - * AuthController constructor. + * OCSAuthAPI constructor. * * @param IRequest $request * @param ISecureRandom $secureRandom - * @param JobList $jobList + * @param IJobList $jobList * @param TrustedServers $trustedServers * @param DbHandler $dbHandler */ public function __construct( IRequest $request, ISecureRandom $secureRandom, - JobList $jobList, + IJobList $jobList, TrustedServers $trustedServers, DbHandler $dbHandler ) { diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php index 72a30f9ae0a..350b140b4dd 100644 --- a/apps/federation/appinfo/application.php +++ b/apps/federation/appinfo/application.php @@ -87,19 +87,6 @@ class Application extends \OCP\AppFramework\App { $c->query('TrustedServers') ); }); - - - $container->registerService('AuthController', function (IAppContainer $c) { - $server = $c->getServer(); - return new AuthController( - $c->getAppName(), - $server->getRequest(), - $server->getSecureRandom(), - $server->getJobList(), - $c->query('TrustedServers'), - $c->query('DbHandler') - ); - }); } private function registerMiddleware() { diff --git a/apps/federation/backgroundjob/getsharedsecret.php b/apps/federation/backgroundjob/getsharedsecret.php index dd095ed117a..88f2a51045a 100644 --- a/apps/federation/backgroundjob/getsharedsecret.php +++ b/apps/federation/backgroundjob/getsharedsecret.php @@ -23,6 +23,7 @@ namespace OCA\Federation\BackgroundJob; use GuzzleHttp\Exception\ClientException; +use OC\BackgroundJob\JobList; use OC\BackgroundJob\QueuedJob; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; diff --git a/apps/federation/backgroundjob/requestsharedsecret.php b/apps/federation/backgroundjob/requestsharedsecret.php index c945757818d..f5685e2e0c2 100644 --- a/apps/federation/backgroundjob/requestsharedsecret.php +++ b/apps/federation/backgroundjob/requestsharedsecret.php @@ -24,6 +24,7 @@ namespace OCA\Federation\BackgroundJob; use GuzzleHttp\Exception\ClientException; +use OC\BackgroundJob\JobList; use OC\BackgroundJob\QueuedJob; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index 2b57dd75419..976a48f8b09 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -82,7 +82,7 @@ class DbHandler { $result = $query->execute(); if ($result) { - return $this->connection->lastInsertId($this->dbTable); + return $this->connection->lastInsertId('*PREFIX*'.$this->dbTable); } else { $message = 'Internal failure, Could not add ownCloud as trusted server: ' . $url; $message_t = $this->l->t('Could not add server'); @@ -110,7 +110,7 @@ class DbHandler { */ public function getAllServer() { $query = $this->connection->getQueryBuilder(); - $query->select('url', 'id', 'status')->from($this->dbTable); + $query->select(['url', 'id', 'status'])->from($this->dbTable); $result = $query->execute()->fetchAll(); return $result; } -- GitLab From 764504de19e573a90789c05f657843d01d6eb28b Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Fri, 20 Nov 2015 01:55:32 -0500 Subject: [PATCH 102/344] [tx-robot] updated from transifex --- apps/files/l10n/th_TH.js | 8 +++++--- apps/files/l10n/th_TH.json | 8 +++++--- apps/files_external/l10n/de.js | 2 +- apps/files_external/l10n/de.json | 2 +- apps/files_external/l10n/de_DE.js | 2 +- apps/files_external/l10n/de_DE.json | 2 +- apps/user_ldap/l10n/th_TH.js | 1 + apps/user_ldap/l10n/th_TH.json | 1 + settings/l10n/ar.js | 1 - settings/l10n/ar.json | 1 - settings/l10n/ast.js | 1 - settings/l10n/ast.json | 1 - settings/l10n/az.js | 1 - settings/l10n/az.json | 1 - settings/l10n/bg_BG.js | 1 - settings/l10n/bg_BG.json | 1 - settings/l10n/bs.js | 1 - settings/l10n/bs.json | 1 - settings/l10n/ca.js | 1 - settings/l10n/ca.json | 1 - settings/l10n/cs_CZ.js | 1 - settings/l10n/cs_CZ.json | 1 - settings/l10n/da.js | 1 - settings/l10n/da.json | 1 - settings/l10n/de.js | 7 +++---- settings/l10n/de.json | 7 +++---- settings/l10n/de_DE.js | 5 ++--- settings/l10n/de_DE.json | 5 ++--- settings/l10n/el.js | 1 - settings/l10n/el.json | 1 - settings/l10n/en_GB.js | 1 - settings/l10n/en_GB.json | 1 - settings/l10n/eo.js | 1 - settings/l10n/eo.json | 1 - settings/l10n/es.js | 1 - settings/l10n/es.json | 1 - settings/l10n/es_AR.js | 1 - settings/l10n/es_AR.json | 1 - settings/l10n/es_MX.js | 1 - settings/l10n/es_MX.json | 1 - settings/l10n/et_EE.js | 1 - settings/l10n/et_EE.json | 1 - settings/l10n/eu.js | 1 - settings/l10n/eu.json | 1 - settings/l10n/fa.js | 1 - settings/l10n/fa.json | 1 - settings/l10n/fi_FI.js | 1 - settings/l10n/fi_FI.json | 1 - settings/l10n/fr.js | 1 - settings/l10n/fr.json | 1 - settings/l10n/gl.js | 1 - settings/l10n/gl.json | 1 - settings/l10n/he.js | 1 - settings/l10n/he.json | 1 - settings/l10n/hr.js | 1 - settings/l10n/hr.json | 1 - settings/l10n/hu_HU.js | 1 - settings/l10n/hu_HU.json | 1 - settings/l10n/id.js | 1 - settings/l10n/id.json | 1 - settings/l10n/it.js | 1 - settings/l10n/it.json | 1 - settings/l10n/ja.js | 1 - settings/l10n/ja.json | 1 - settings/l10n/ka_GE.js | 1 - settings/l10n/ka_GE.json | 1 - settings/l10n/km.js | 1 - settings/l10n/km.json | 1 - settings/l10n/kn.js | 1 - settings/l10n/kn.json | 1 - settings/l10n/ko.js | 1 - settings/l10n/ko.json | 1 - settings/l10n/lt_LT.js | 1 - settings/l10n/lt_LT.json | 1 - settings/l10n/lv.js | 1 - settings/l10n/lv.json | 1 - settings/l10n/mk.js | 1 - settings/l10n/mk.json | 1 - settings/l10n/ms_MY.js | 1 - settings/l10n/ms_MY.json | 1 - settings/l10n/nb_NO.js | 1 - settings/l10n/nb_NO.json | 1 - settings/l10n/nl.js | 1 - settings/l10n/nl.json | 1 - settings/l10n/nn_NO.js | 1 - settings/l10n/nn_NO.json | 1 - settings/l10n/oc.js | 1 - settings/l10n/oc.json | 1 - settings/l10n/pl.js | 1 - settings/l10n/pl.json | 1 - settings/l10n/pt_BR.js | 1 - settings/l10n/pt_BR.json | 1 - settings/l10n/pt_PT.js | 1 - settings/l10n/pt_PT.json | 1 - settings/l10n/ro.js | 1 - settings/l10n/ro.json | 1 - settings/l10n/ru.js | 1 - settings/l10n/ru.json | 1 - settings/l10n/sk_SK.js | 1 - settings/l10n/sk_SK.json | 1 - settings/l10n/sl.js | 1 - settings/l10n/sl.json | 1 - settings/l10n/sq.js | 1 - settings/l10n/sq.json | 1 - settings/l10n/sr.js | 1 - settings/l10n/sr.json | 1 - settings/l10n/sv.js | 1 - settings/l10n/sv.json | 1 - settings/l10n/th_TH.js | 1 - settings/l10n/th_TH.json | 1 - settings/l10n/tr.js | 1 - settings/l10n/tr.json | 1 - settings/l10n/ug.js | 1 - settings/l10n/ug.json | 1 - settings/l10n/uk.js | 1 - settings/l10n/uk.json | 1 - settings/l10n/zh_CN.js | 1 - settings/l10n/zh_CN.json | 1 - settings/l10n/zh_HK.js | 1 - settings/l10n/zh_HK.json | 1 - settings/l10n/zh_TW.js | 1 - settings/l10n/zh_TW.json | 1 - 122 files changed, 26 insertions(+), 134 deletions(-) diff --git a/apps/files/l10n/th_TH.js b/apps/files/l10n/th_TH.js index 1194c11ced1..79747b68ee9 100644 --- a/apps/files/l10n/th_TH.js +++ b/apps/files/l10n/th_TH.js @@ -75,8 +75,6 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n ไบต์"], "Favorited" : "รายการโปรด", "Favorite" : "รายการโปรด", - "Text file" : "ไฟล์ข้อความ", - "New text file.txt" : "ไฟล์ข้อความใหม่ .txt", "Folder" : "แฟ้มเอกสาร", "New folder" : "โฟลเดอร์ใหม่", "{newname} already exists" : "{newname} ถูกใช้ไปแล้ว", @@ -106,6 +104,8 @@ OC.L10N.register( "Maximum upload size" : "ขนาดไฟล์สูงสุดที่อัพโหลดได้", "max. possible: " : "จำนวนสูงสุดที่สามารถทำได้: ", "Save" : "บันทึก", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "กับ PHP-FPM อาจใช้เวลา 5 นาทีสำหรับการเปลี่ยนแปลงที่ถูกนำมาใช้", + "Missing permissions to edit from here." : "สิทธิ์ในการแก้ไขส่วนนี้หายไป", "Settings" : "ตั้งค่า", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "ใช้ที่อยู่นี้เพื่อ เข้าถึงไฟล์ของคุณผ่าน WebDAV", @@ -119,6 +119,8 @@ OC.L10N.register( "Files are being scanned, please wait." : "ไฟล์กำลังอยู่ระหว่างการสแกน, กรุณารอสักครู่.", "Currently scanning" : "ปัจจุบันกำลังสแกน", "No favorites" : "ไม่มีรายการโปรด", - "Files and folders you mark as favorite will show up here" : "ไฟล์และโฟลเดอร์ที่คุณทำเครื่องหมายเป็นรายการโปรดจะปรากฏขึ้นที่นี่" + "Files and folders you mark as favorite will show up here" : "ไฟล์และโฟลเดอร์ที่คุณทำเครื่องหมายเป็นรายการโปรดจะปรากฏขึ้นที่นี่", + "Text file" : "ไฟล์ข้อความ", + "New text file.txt" : "ไฟล์ข้อความใหม่ .txt" }, "nplurals=1; plural=0;"); diff --git a/apps/files/l10n/th_TH.json b/apps/files/l10n/th_TH.json index 80f80e54ddf..327e2d9eb82 100644 --- a/apps/files/l10n/th_TH.json +++ b/apps/files/l10n/th_TH.json @@ -73,8 +73,6 @@ "_%n byte_::_%n bytes_" : ["%n ไบต์"], "Favorited" : "รายการโปรด", "Favorite" : "รายการโปรด", - "Text file" : "ไฟล์ข้อความ", - "New text file.txt" : "ไฟล์ข้อความใหม่ .txt", "Folder" : "แฟ้มเอกสาร", "New folder" : "โฟลเดอร์ใหม่", "{newname} already exists" : "{newname} ถูกใช้ไปแล้ว", @@ -104,6 +102,8 @@ "Maximum upload size" : "ขนาดไฟล์สูงสุดที่อัพโหลดได้", "max. possible: " : "จำนวนสูงสุดที่สามารถทำได้: ", "Save" : "บันทึก", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "กับ PHP-FPM อาจใช้เวลา 5 นาทีสำหรับการเปลี่ยนแปลงที่ถูกนำมาใช้", + "Missing permissions to edit from here." : "สิทธิ์ในการแก้ไขส่วนนี้หายไป", "Settings" : "ตั้งค่า", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "ใช้ที่อยู่นี้เพื่อ เข้าถึงไฟล์ของคุณผ่าน WebDAV", @@ -117,6 +117,8 @@ "Files are being scanned, please wait." : "ไฟล์กำลังอยู่ระหว่างการสแกน, กรุณารอสักครู่.", "Currently scanning" : "ปัจจุบันกำลังสแกน", "No favorites" : "ไม่มีรายการโปรด", - "Files and folders you mark as favorite will show up here" : "ไฟล์และโฟลเดอร์ที่คุณทำเครื่องหมายเป็นรายการโปรดจะปรากฏขึ้นที่นี่" + "Files and folders you mark as favorite will show up here" : "ไฟล์และโฟลเดอร์ที่คุณทำเครื่องหมายเป็นรายการโปรดจะปรากฏขึ้นที่นี่", + "Text file" : "ไฟล์ข้อความ", + "New text file.txt" : "ไฟล์ข้อความใหม่ .txt" },"pluralForm" :"nplurals=1; plural=0;" } \ No newline at end of file diff --git a/apps/files_external/l10n/de.js b/apps/files_external/l10n/de.js index c26322495d6..a51cc52a247 100644 --- a/apps/files_external/l10n/de.js +++ b/apps/files_external/l10n/de.js @@ -87,6 +87,6 @@ OC.L10N.register( "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Allow users to mount the following external storage" : "Erlaube es Benutzern, den folgenden externen Speicher einzubinden" + "Allow users to mount the following external storage" : "Benutzern erlauben, den oder die folgenden externen Speicher einzubinden:" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/de.json b/apps/files_external/l10n/de.json index adec32d072b..41ecaad2594 100644 --- a/apps/files_external/l10n/de.json +++ b/apps/files_external/l10n/de.json @@ -85,6 +85,6 @@ "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Allow users to mount the following external storage" : "Erlaube es Benutzern, den folgenden externen Speicher einzubinden" + "Allow users to mount the following external storage" : "Benutzern erlauben, den oder die folgenden externen Speicher einzubinden:" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/files_external/l10n/de_DE.js b/apps/files_external/l10n/de_DE.js index c30fcb95919..610f737a4a8 100644 --- a/apps/files_external/l10n/de_DE.js +++ b/apps/files_external/l10n/de_DE.js @@ -70,6 +70,6 @@ OC.L10N.register( "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Allow users to mount the following external storage" : "Erlauben Sie Benutzern, folgende externe Speicher einzubinden" + "Allow users to mount the following external storage" : "Benutzern erlauben, den oder die folgenden externen Speicher einzubinden:" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/de_DE.json b/apps/files_external/l10n/de_DE.json index 7fec06bf90f..fa21fea8f4a 100644 --- a/apps/files_external/l10n/de_DE.json +++ b/apps/files_external/l10n/de_DE.json @@ -68,6 +68,6 @@ "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Allow users to mount the following external storage" : "Erlauben Sie Benutzern, folgende externe Speicher einzubinden" + "Allow users to mount the following external storage" : "Benutzern erlauben, den oder die folgenden externen Speicher einzubinden:" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/user_ldap/l10n/th_TH.js b/apps/user_ldap/l10n/th_TH.js index c848d137464..8b155dcfe23 100644 --- a/apps/user_ldap/l10n/th_TH.js +++ b/apps/user_ldap/l10n/th_TH.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "ไม่สามารถตรวจสอบ Base DN โปรดเลือกด้วยตนเอง", "{nthServer}. Server" : "เซิร์ฟเวอร์ {nthServer}", "No object found in the given Base DN. Please revise." : "ไม่พบวัตถุที่กำหนดใน Base DN กรุณาแก้ไข", + "More than 1,000 directory entries available." : "ไดเรกทอรีมีอยู่มากกว่า 1,000 รายการ", " entries available within the provided Base DN" : "รายการที่มีอยู่ใน Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "เกิดข้อผิดพลาด กรุณาตรวจสอบ Base DN เช่นเดียวกับการตั้งค่าการเชื่อมต่อและข้อมูลที่สำคัญ", "Do you really want to delete the current Server Configuration?" : "คุณแน่ใจแล้วหรือว่าต้องการลบการกำหนดค่าเซิร์ฟเวอร์ปัจจุบันทิ้งไป?", diff --git a/apps/user_ldap/l10n/th_TH.json b/apps/user_ldap/l10n/th_TH.json index 6afa6f2bbc4..9787ba10037 100644 --- a/apps/user_ldap/l10n/th_TH.json +++ b/apps/user_ldap/l10n/th_TH.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "ไม่สามารถตรวจสอบ Base DN โปรดเลือกด้วยตนเอง", "{nthServer}. Server" : "เซิร์ฟเวอร์ {nthServer}", "No object found in the given Base DN. Please revise." : "ไม่พบวัตถุที่กำหนดใน Base DN กรุณาแก้ไข", + "More than 1,000 directory entries available." : "ไดเรกทอรีมีอยู่มากกว่า 1,000 รายการ", " entries available within the provided Base DN" : "รายการที่มีอยู่ใน Base DN", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "เกิดข้อผิดพลาด กรุณาตรวจสอบ Base DN เช่นเดียวกับการตั้งค่าการเชื่อมต่อและข้อมูลที่สำคัญ", "Do you really want to delete the current Server Configuration?" : "คุณแน่ใจแล้วหรือว่าต้องการลบการกำหนดค่าเซิร์ฟเวอร์ปัจจุบันทิ้งไป?", diff --git a/settings/l10n/ar.js b/settings/l10n/ar.js index a4e9705f3ac..818d001b3d6 100644 --- a/settings/l10n/ar.js +++ b/settings/l10n/ar.js @@ -73,7 +73,6 @@ OC.L10N.register( "Authentication method" : "أسلوب التطابق", "Server address" : "عنوان الخادم", "Port" : "المنفذ", - "Log level" : "مستوى السجل", "More" : "المزيد", "Less" : "أقل", "Version" : "إصدار", diff --git a/settings/l10n/ar.json b/settings/l10n/ar.json index 1bd8a54f022..6e2a8268b5f 100644 --- a/settings/l10n/ar.json +++ b/settings/l10n/ar.json @@ -71,7 +71,6 @@ "Authentication method" : "أسلوب التطابق", "Server address" : "عنوان الخادم", "Port" : "المنفذ", - "Log level" : "مستوى السجل", "More" : "المزيد", "Less" : "أقل", "Version" : "إصدار", diff --git a/settings/l10n/ast.js b/settings/l10n/ast.js index 56e47c9f263..9597cc9a522 100644 --- a/settings/l10n/ast.js +++ b/settings/l10n/ast.js @@ -113,7 +113,6 @@ OC.L10N.register( "SMTP Password" : "Contraseña SMTP", "Test email settings" : "Probar configuración de corréu electrónicu", "Send email" : "Unviar mensaxe", - "Log level" : "Nivel de rexistru", "More" : "Más", "Less" : "Menos", "Version" : "Versión", diff --git a/settings/l10n/ast.json b/settings/l10n/ast.json index 3d976d01145..c3252ba8bf5 100644 --- a/settings/l10n/ast.json +++ b/settings/l10n/ast.json @@ -111,7 +111,6 @@ "SMTP Password" : "Contraseña SMTP", "Test email settings" : "Probar configuración de corréu electrónicu", "Send email" : "Unviar mensaxe", - "Log level" : "Nivel de rexistru", "More" : "Más", "Less" : "Menos", "Version" : "Versión", diff --git a/settings/l10n/az.js b/settings/l10n/az.js index f1c034013bb..60a2492a282 100644 --- a/settings/l10n/az.js +++ b/settings/l10n/az.js @@ -145,7 +145,6 @@ OC.L10N.register( "Store credentials" : "Səlahiyyətləri saxla", "Test email settings" : "Email qurmalarını test et", "Send email" : "Email yolla", - "Log level" : "Jurnal səviyyəsi", "Download logfile" : "Jurnal faylını endir", "More" : "Yenə", "Less" : "Az", diff --git a/settings/l10n/az.json b/settings/l10n/az.json index b67082c4269..8b46a472df7 100644 --- a/settings/l10n/az.json +++ b/settings/l10n/az.json @@ -143,7 +143,6 @@ "Store credentials" : "Səlahiyyətləri saxla", "Test email settings" : "Email qurmalarını test et", "Send email" : "Email yolla", - "Log level" : "Jurnal səviyyəsi", "Download logfile" : "Jurnal faylını endir", "More" : "Yenə", "Less" : "Az", diff --git a/settings/l10n/bg_BG.js b/settings/l10n/bg_BG.js index caef15f4bff..425b8f47dc7 100644 --- a/settings/l10n/bg_BG.js +++ b/settings/l10n/bg_BG.js @@ -142,7 +142,6 @@ OC.L10N.register( "Store credentials" : "Запазвай креденциите", "Test email settings" : "Настройки на проверяващия имейл", "Send email" : "Изпрати имейл", - "Log level" : "Детайли на доклада", "Download logfile" : "Изтегли log файла", "More" : "Още", "Less" : "По-малко", diff --git a/settings/l10n/bg_BG.json b/settings/l10n/bg_BG.json index cf4bcb5182a..e12faed8f69 100644 --- a/settings/l10n/bg_BG.json +++ b/settings/l10n/bg_BG.json @@ -140,7 +140,6 @@ "Store credentials" : "Запазвай креденциите", "Test email settings" : "Настройки на проверяващия имейл", "Send email" : "Изпрати имейл", - "Log level" : "Детайли на доклада", "Download logfile" : "Изтегли log файла", "More" : "Още", "Less" : "По-малко", diff --git a/settings/l10n/bs.js b/settings/l10n/bs.js index b98bc00fd6a..feafcfe9661 100644 --- a/settings/l10n/bs.js +++ b/settings/l10n/bs.js @@ -128,7 +128,6 @@ OC.L10N.register( "Store credentials" : "Spremi vjerodajnice", "Test email settings" : "Postavke za testnu e-poštu", "Send email" : "Pošalji e-poštu", - "Log level" : "Razina zapisnika", "More" : "Više", "Less" : "Manje", "Version" : "Verzija", diff --git a/settings/l10n/bs.json b/settings/l10n/bs.json index 25b5ec57d41..ece2026bc23 100644 --- a/settings/l10n/bs.json +++ b/settings/l10n/bs.json @@ -126,7 +126,6 @@ "Store credentials" : "Spremi vjerodajnice", "Test email settings" : "Postavke za testnu e-poštu", "Send email" : "Pošalji e-poštu", - "Log level" : "Razina zapisnika", "More" : "Više", "Less" : "Manje", "Version" : "Verzija", diff --git a/settings/l10n/ca.js b/settings/l10n/ca.js index 54328d47ca7..1725d278b4f 100644 --- a/settings/l10n/ca.js +++ b/settings/l10n/ca.js @@ -161,7 +161,6 @@ OC.L10N.register( "Store credentials" : "Emmagatzemar credencials", "Test email settings" : "Prova l'arranjament del correu", "Send email" : "Envia correu", - "Log level" : "Nivell de registre", "Download logfile" : "Descarregar arxiu de registre", "More" : "Més", "Less" : "Menys", diff --git a/settings/l10n/ca.json b/settings/l10n/ca.json index bb758dca212..39f569a4a11 100644 --- a/settings/l10n/ca.json +++ b/settings/l10n/ca.json @@ -159,7 +159,6 @@ "Store credentials" : "Emmagatzemar credencials", "Test email settings" : "Prova l'arranjament del correu", "Send email" : "Envia correu", - "Log level" : "Nivell de registre", "Download logfile" : "Descarregar arxiu de registre", "More" : "Més", "Less" : "Menys", diff --git a/settings/l10n/cs_CZ.js b/settings/l10n/cs_CZ.js index fc819461f4f..e1097fc485f 100644 --- a/settings/l10n/cs_CZ.js +++ b/settings/l10n/cs_CZ.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Ukládat přihlašovací údaje", "Test email settings" : "Otestovat nastavení emailu", "Send email" : "Odeslat email", - "Log level" : "Úroveň zaznamenávání", "Download logfile" : "Stáhnout soubor logu", "More" : "Více", "Less" : "Méně", diff --git a/settings/l10n/cs_CZ.json b/settings/l10n/cs_CZ.json index 598267f3de7..9e3b9a7b72c 100644 --- a/settings/l10n/cs_CZ.json +++ b/settings/l10n/cs_CZ.json @@ -186,7 +186,6 @@ "Store credentials" : "Ukládat přihlašovací údaje", "Test email settings" : "Otestovat nastavení emailu", "Send email" : "Odeslat email", - "Log level" : "Úroveň zaznamenávání", "Download logfile" : "Stáhnout soubor logu", "More" : "Více", "Less" : "Méně", diff --git a/settings/l10n/da.js b/settings/l10n/da.js index fd9e5734530..b69c9d248de 100644 --- a/settings/l10n/da.js +++ b/settings/l10n/da.js @@ -181,7 +181,6 @@ OC.L10N.register( "Store credentials" : "Gem brugeroplysninger", "Test email settings" : "Test e-mail-indstillinger", "Send email" : "Send e-mail", - "Log level" : "Log niveau", "Download logfile" : "Hent logfil", "More" : "Mere", "Less" : "Mindre", diff --git a/settings/l10n/da.json b/settings/l10n/da.json index af6f5367a9c..1519317def9 100644 --- a/settings/l10n/da.json +++ b/settings/l10n/da.json @@ -179,7 +179,6 @@ "Store credentials" : "Gem brugeroplysninger", "Test email settings" : "Test e-mail-indstillinger", "Send email" : "Send e-mail", - "Log level" : "Log niveau", "Download logfile" : "Hent logfil", "More" : "Mere", "Less" : "Mindre", diff --git a/settings/l10n/de.js b/settings/l10n/de.js index 5d5a4d955c1..a0c762076bb 100644 --- a/settings/l10n/de.js +++ b/settings/l10n/de.js @@ -136,16 +136,16 @@ OC.L10N.register( "Please double check the installation guides ↗, and check for any errors or warnings in the log." : "Bitte überprüfe noch einmal die Installationsanleitungen ↗ und kontrolliere das Log auf mögliche Fehler oder Warnungen.", "All checks passed." : "Alle Überprüfungen bestanden.", "Open documentation" : "Dokumentation öffnen", - "Allow apps to use the Share API" : "Erlaubt Apps die Nutzung der Share-API", + "Allow apps to use the Share API" : "Apps die Benutzung der Share-API erlauben", "Allow users to share via link" : "Benutzern erlauben, Inhalte über Links zu teilen", "Enforce password protection" : "Passwortschutz erzwingen", "Allow public uploads" : "Öffentliches Hochladen erlauben", "Allow users to send mail notification for shared files" : "Benutzern erlauben, E-Mail-Benachrichtigungen für freigegebene Dateien zu senden", - "Set default expiration date" : "Setze Ablaufdatum", + "Set default expiration date" : "Standardmäßiges Ablaufdatum setzen", "Expire after " : "Ablauf nach ", "days" : "Tagen", "Enforce expiration date" : "Ablaufdatum erzwingen", - "Allow resharing" : "Erlaubt erneutes Teilen", + "Allow resharing" : "Weiterverteilen erlauben", "Restrict users to only share with users in their groups" : "Benutzer auf das Teilen innerhalb ihrer Gruppen beschränken", "Allow users to send mail notification for shared files to other users" : "Benutzern erlauben, E-Mail-Benachrichtigungen für freigegebene Dateien an andere Benutzer zu senden", "Exclude groups from sharing" : "Gruppen von Freigaben ausschließen", @@ -181,7 +181,6 @@ OC.L10N.register( "Store credentials" : "Anmeldeinformationen speichern", "Test email settings" : "E-Mail-Einstellungen testen", "Send email" : "E-Mail senden", - "Log level" : "Loglevel", "Download logfile" : "Logdatei herunterladen", "More" : "Mehr", "Less" : "Weniger", diff --git a/settings/l10n/de.json b/settings/l10n/de.json index 9bd8d36dac3..be68541cab9 100644 --- a/settings/l10n/de.json +++ b/settings/l10n/de.json @@ -134,16 +134,16 @@ "Please double check the installation guides ↗, and check for any errors or warnings in the log." : "Bitte überprüfe noch einmal die Installationsanleitungen ↗ und kontrolliere das Log auf mögliche Fehler oder Warnungen.", "All checks passed." : "Alle Überprüfungen bestanden.", "Open documentation" : "Dokumentation öffnen", - "Allow apps to use the Share API" : "Erlaubt Apps die Nutzung der Share-API", + "Allow apps to use the Share API" : "Apps die Benutzung der Share-API erlauben", "Allow users to share via link" : "Benutzern erlauben, Inhalte über Links zu teilen", "Enforce password protection" : "Passwortschutz erzwingen", "Allow public uploads" : "Öffentliches Hochladen erlauben", "Allow users to send mail notification for shared files" : "Benutzern erlauben, E-Mail-Benachrichtigungen für freigegebene Dateien zu senden", - "Set default expiration date" : "Setze Ablaufdatum", + "Set default expiration date" : "Standardmäßiges Ablaufdatum setzen", "Expire after " : "Ablauf nach ", "days" : "Tagen", "Enforce expiration date" : "Ablaufdatum erzwingen", - "Allow resharing" : "Erlaubt erneutes Teilen", + "Allow resharing" : "Weiterverteilen erlauben", "Restrict users to only share with users in their groups" : "Benutzer auf das Teilen innerhalb ihrer Gruppen beschränken", "Allow users to send mail notification for shared files to other users" : "Benutzern erlauben, E-Mail-Benachrichtigungen für freigegebene Dateien an andere Benutzer zu senden", "Exclude groups from sharing" : "Gruppen von Freigaben ausschließen", @@ -179,7 +179,6 @@ "Store credentials" : "Anmeldeinformationen speichern", "Test email settings" : "E-Mail-Einstellungen testen", "Send email" : "E-Mail senden", - "Log level" : "Loglevel", "Download logfile" : "Logdatei herunterladen", "More" : "Mehr", "Less" : "Weniger", diff --git a/settings/l10n/de_DE.js b/settings/l10n/de_DE.js index fd8938d0b51..ec994697e6a 100644 --- a/settings/l10n/de_DE.js +++ b/settings/l10n/de_DE.js @@ -129,12 +129,12 @@ OC.L10N.register( "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Die Ausführung des Cron-Jobs über die Kommandozeile war nicht möglich. Die folgenden technischen Fehler sind dabei aufgetreten:", "Please double check the installation guides ↗, and check for any errors or warnings in the log." : "Bitte überprüfen Sie noch einmal die Installationsanleitungen ↗ und kontrollieren Sie das Log auf mögliche Fehler oder Warnungen.", "Open documentation" : "Dokumentation öffnen", - "Allow apps to use the Share API" : "Anwendungen erlauben, die Share-API zu benutzen", + "Allow apps to use the Share API" : "Apps die Benutzung der Share-API erlauben", "Allow users to share via link" : "Benutzern erlauben, Inhalte über Links zu teilen", "Enforce password protection" : "Passwortschutz erzwingen", "Allow public uploads" : "Öffentliches Hochladen erlauben", "Allow users to send mail notification for shared files" : "Benutzern erlauben, E-Mail-Benachrichtigungen für freigegebene Dateien zu senden", - "Set default expiration date" : "Standardablaufdatum einstellen", + "Set default expiration date" : "Standardmäßiges Ablaufdatum setzen", "Expire after " : "Ablauf nach ", "days" : "Tagen", "Enforce expiration date" : "Ablaufdatum erzwingen", @@ -171,7 +171,6 @@ OC.L10N.register( "Store credentials" : "Anmeldeinformationen speichern", "Test email settings" : "E-Mail-Einstellungen testen", "Send email" : "E-Mail senden", - "Log level" : "Log-Level", "Download logfile" : "Logdatei herunterladen", "More" : "Mehr", "Less" : "Weniger", diff --git a/settings/l10n/de_DE.json b/settings/l10n/de_DE.json index 1f0adec9b56..f1b0b60faf1 100644 --- a/settings/l10n/de_DE.json +++ b/settings/l10n/de_DE.json @@ -127,12 +127,12 @@ "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Die Ausführung des Cron-Jobs über die Kommandozeile war nicht möglich. Die folgenden technischen Fehler sind dabei aufgetreten:", "Please double check the installation guides ↗, and check for any errors or warnings in the log." : "Bitte überprüfen Sie noch einmal die Installationsanleitungen ↗ und kontrollieren Sie das Log auf mögliche Fehler oder Warnungen.", "Open documentation" : "Dokumentation öffnen", - "Allow apps to use the Share API" : "Anwendungen erlauben, die Share-API zu benutzen", + "Allow apps to use the Share API" : "Apps die Benutzung der Share-API erlauben", "Allow users to share via link" : "Benutzern erlauben, Inhalte über Links zu teilen", "Enforce password protection" : "Passwortschutz erzwingen", "Allow public uploads" : "Öffentliches Hochladen erlauben", "Allow users to send mail notification for shared files" : "Benutzern erlauben, E-Mail-Benachrichtigungen für freigegebene Dateien zu senden", - "Set default expiration date" : "Standardablaufdatum einstellen", + "Set default expiration date" : "Standardmäßiges Ablaufdatum setzen", "Expire after " : "Ablauf nach ", "days" : "Tagen", "Enforce expiration date" : "Ablaufdatum erzwingen", @@ -169,7 +169,6 @@ "Store credentials" : "Anmeldeinformationen speichern", "Test email settings" : "E-Mail-Einstellungen testen", "Send email" : "E-Mail senden", - "Log level" : "Log-Level", "Download logfile" : "Logdatei herunterladen", "More" : "Mehr", "Less" : "Weniger", diff --git a/settings/l10n/el.js b/settings/l10n/el.js index ab9b47b366c..acb9dca3dfd 100644 --- a/settings/l10n/el.js +++ b/settings/l10n/el.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Διαπιστευτήρια αποθήκευσης", "Test email settings" : "Δοκιμή ρυθμίσεων email", "Send email" : "Αποστολή email", - "Log level" : "Επίπεδο καταγραφής", "Download logfile" : "Λήψη αρχείου ιστορικού", "More" : "Περισσότερα", "Less" : "Λιγότερα", diff --git a/settings/l10n/el.json b/settings/l10n/el.json index c355f70dd82..42d6dd01ceb 100644 --- a/settings/l10n/el.json +++ b/settings/l10n/el.json @@ -186,7 +186,6 @@ "Store credentials" : "Διαπιστευτήρια αποθήκευσης", "Test email settings" : "Δοκιμή ρυθμίσεων email", "Send email" : "Αποστολή email", - "Log level" : "Επίπεδο καταγραφής", "Download logfile" : "Λήψη αρχείου ιστορικού", "More" : "Περισσότερα", "Less" : "Λιγότερα", diff --git a/settings/l10n/en_GB.js b/settings/l10n/en_GB.js index 0a51d19bb6d..5a4a1a3c998 100644 --- a/settings/l10n/en_GB.js +++ b/settings/l10n/en_GB.js @@ -167,7 +167,6 @@ OC.L10N.register( "Store credentials" : "Store credentials", "Test email settings" : "Test email settings", "Send email" : "Send email", - "Log level" : "Log level", "Download logfile" : "Download logfile", "More" : "More", "Less" : "Less", diff --git a/settings/l10n/en_GB.json b/settings/l10n/en_GB.json index a696c3dcbc1..4f1e2efc456 100644 --- a/settings/l10n/en_GB.json +++ b/settings/l10n/en_GB.json @@ -165,7 +165,6 @@ "Store credentials" : "Store credentials", "Test email settings" : "Test email settings", "Send email" : "Send email", - "Log level" : "Log level", "Download logfile" : "Download logfile", "More" : "More", "Less" : "Less", diff --git a/settings/l10n/eo.js b/settings/l10n/eo.js index 196fcff74d2..ca4b5485d50 100644 --- a/settings/l10n/eo.js +++ b/settings/l10n/eo.js @@ -79,7 +79,6 @@ OC.L10N.register( "SMTP Username" : "SMTP-uzantonomo", "SMTP Password" : "SMTP-pasvorto", "Send email" : "Sendi retpoŝton", - "Log level" : "Registronivelo", "More" : "Pli", "Less" : "Malpli", "Version" : "Eldono", diff --git a/settings/l10n/eo.json b/settings/l10n/eo.json index 791dca9b499..3df0eda6e8e 100644 --- a/settings/l10n/eo.json +++ b/settings/l10n/eo.json @@ -77,7 +77,6 @@ "SMTP Username" : "SMTP-uzantonomo", "SMTP Password" : "SMTP-pasvorto", "Send email" : "Sendi retpoŝton", - "Log level" : "Registronivelo", "More" : "Pli", "Less" : "Malpli", "Version" : "Eldono", diff --git a/settings/l10n/es.js b/settings/l10n/es.js index 9a45c5b7457..36d9d9392e1 100644 --- a/settings/l10n/es.js +++ b/settings/l10n/es.js @@ -185,7 +185,6 @@ OC.L10N.register( "Store credentials" : "Almacenar credenciales", "Test email settings" : "Probar configuración de correo electrónico", "Send email" : "Enviar mensaje", - "Log level" : "Nivel de registro", "Download logfile" : "Descargar archivo de registro", "More" : "Más", "Less" : "Menos", diff --git a/settings/l10n/es.json b/settings/l10n/es.json index 383f6cb6f8c..87cf83a55f0 100644 --- a/settings/l10n/es.json +++ b/settings/l10n/es.json @@ -183,7 +183,6 @@ "Store credentials" : "Almacenar credenciales", "Test email settings" : "Probar configuración de correo electrónico", "Send email" : "Enviar mensaje", - "Log level" : "Nivel de registro", "Download logfile" : "Descargar archivo de registro", "More" : "Más", "Less" : "Menos", diff --git a/settings/l10n/es_AR.js b/settings/l10n/es_AR.js index 122422aac97..14b4c6457da 100644 --- a/settings/l10n/es_AR.js +++ b/settings/l10n/es_AR.js @@ -85,7 +85,6 @@ OC.L10N.register( "SMTP Password" : "Contraseña SMTP", "Test email settings" : "Configuracion de correo de prueba.", "Send email" : "Enviar correo", - "Log level" : "Nivel de Log", "More" : "Más", "Less" : "Menos", "Version" : "Versión", diff --git a/settings/l10n/es_AR.json b/settings/l10n/es_AR.json index 72e593031b8..c03a8ef96db 100644 --- a/settings/l10n/es_AR.json +++ b/settings/l10n/es_AR.json @@ -83,7 +83,6 @@ "SMTP Password" : "Contraseña SMTP", "Test email settings" : "Configuracion de correo de prueba.", "Send email" : "Enviar correo", - "Log level" : "Nivel de Log", "More" : "Más", "Less" : "Menos", "Version" : "Versión", diff --git a/settings/l10n/es_MX.js b/settings/l10n/es_MX.js index 3111101135b..0a83ff50f1a 100644 --- a/settings/l10n/es_MX.js +++ b/settings/l10n/es_MX.js @@ -62,7 +62,6 @@ OC.L10N.register( "Encryption" : "Cifrado", "Server address" : "Dirección del servidor", "Port" : "Puerto", - "Log level" : "Nivel de registro", "More" : "Más", "Less" : "Menos", "Version" : "Versión", diff --git a/settings/l10n/es_MX.json b/settings/l10n/es_MX.json index d0cd473e262..a83dfef8048 100644 --- a/settings/l10n/es_MX.json +++ b/settings/l10n/es_MX.json @@ -60,7 +60,6 @@ "Encryption" : "Cifrado", "Server address" : "Dirección del servidor", "Port" : "Puerto", - "Log level" : "Nivel de registro", "More" : "Más", "Less" : "Menos", "Version" : "Versión", diff --git a/settings/l10n/et_EE.js b/settings/l10n/et_EE.js index 67cbca7f5a3..e783531d6cf 100644 --- a/settings/l10n/et_EE.js +++ b/settings/l10n/et_EE.js @@ -149,7 +149,6 @@ OC.L10N.register( "Store credentials" : "Säilita kasutajaandmed", "Test email settings" : "Testi e-posti seadeid", "Send email" : "Saada kiri", - "Log level" : "Logi tase", "Download logfile" : "Laadi logifail alla", "More" : "Rohkem", "Less" : "Vähem", diff --git a/settings/l10n/et_EE.json b/settings/l10n/et_EE.json index 2cdd0499415..95416aad773 100644 --- a/settings/l10n/et_EE.json +++ b/settings/l10n/et_EE.json @@ -147,7 +147,6 @@ "Store credentials" : "Säilita kasutajaandmed", "Test email settings" : "Testi e-posti seadeid", "Send email" : "Saada kiri", - "Log level" : "Logi tase", "Download logfile" : "Laadi logifail alla", "More" : "Rohkem", "Less" : "Vähem", diff --git a/settings/l10n/eu.js b/settings/l10n/eu.js index 0c835b5b233..486cdc74817 100644 --- a/settings/l10n/eu.js +++ b/settings/l10n/eu.js @@ -134,7 +134,6 @@ OC.L10N.register( "Store credentials" : "Gorde kredentzialak", "Test email settings" : "Probatu eposta ezarpenak", "Send email" : "Bidali eposta", - "Log level" : "Erregistro maila", "Download logfile" : "Deskargatu log fitxategia", "More" : "Gehiago", "Less" : "Gutxiago", diff --git a/settings/l10n/eu.json b/settings/l10n/eu.json index 1ade6fad49c..218241db953 100644 --- a/settings/l10n/eu.json +++ b/settings/l10n/eu.json @@ -132,7 +132,6 @@ "Store credentials" : "Gorde kredentzialak", "Test email settings" : "Probatu eposta ezarpenak", "Send email" : "Bidali eposta", - "Log level" : "Erregistro maila", "Download logfile" : "Deskargatu log fitxategia", "More" : "Gehiago", "Less" : "Gutxiago", diff --git a/settings/l10n/fa.js b/settings/l10n/fa.js index 3d9aba76345..299505e1560 100644 --- a/settings/l10n/fa.js +++ b/settings/l10n/fa.js @@ -144,7 +144,6 @@ OC.L10N.register( "SMTP Password" : "رمز عبور SMTP", "Test email settings" : "تنظیمات ایمیل آزمایشی", "Send email" : "ارسال ایمیل", - "Log level" : "سطح ورود", "Download logfile" : "دانلود فایل لاگ", "More" : "بیش‌تر", "Less" : "کم‌تر", diff --git a/settings/l10n/fa.json b/settings/l10n/fa.json index f152587d529..e07f0633e9f 100644 --- a/settings/l10n/fa.json +++ b/settings/l10n/fa.json @@ -142,7 +142,6 @@ "SMTP Password" : "رمز عبور SMTP", "Test email settings" : "تنظیمات ایمیل آزمایشی", "Send email" : "ارسال ایمیل", - "Log level" : "سطح ورود", "Download logfile" : "دانلود فایل لاگ", "More" : "بیش‌تر", "Less" : "کم‌تر", diff --git a/settings/l10n/fi_FI.js b/settings/l10n/fi_FI.js index 0099a3f3221..de232eee730 100644 --- a/settings/l10n/fi_FI.js +++ b/settings/l10n/fi_FI.js @@ -176,7 +176,6 @@ OC.L10N.register( "Store credentials" : "Säilytä tilitiedot", "Test email settings" : "Testaa sähköpostiasetukset", "Send email" : "Lähetä sähköpostiviesti", - "Log level" : "Lokitaso", "Download logfile" : "Lataa lokitiedosto", "More" : "Enemmän", "Less" : "Vähemmän", diff --git a/settings/l10n/fi_FI.json b/settings/l10n/fi_FI.json index 8305ac79050..233e8b6386c 100644 --- a/settings/l10n/fi_FI.json +++ b/settings/l10n/fi_FI.json @@ -174,7 +174,6 @@ "Store credentials" : "Säilytä tilitiedot", "Test email settings" : "Testaa sähköpostiasetukset", "Send email" : "Lähetä sähköpostiviesti", - "Log level" : "Lokitaso", "Download logfile" : "Lataa lokitiedosto", "More" : "Enemmän", "Less" : "Vähemmän", diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js index 0e67356f169..e3c2a792389 100644 --- a/settings/l10n/fr.js +++ b/settings/l10n/fr.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Enregistrer les identifiants", "Test email settings" : "Tester les paramètres e-mail", "Send email" : "Envoyer un e-mail", - "Log level" : "Niveau de log", "Download logfile" : "Télécharger le fichier de journalisation", "More" : "Plus", "Less" : "Moins", diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json index c3e1d6eb176..a0722035b7e 100644 --- a/settings/l10n/fr.json +++ b/settings/l10n/fr.json @@ -186,7 +186,6 @@ "Store credentials" : "Enregistrer les identifiants", "Test email settings" : "Tester les paramètres e-mail", "Send email" : "Envoyer un e-mail", - "Log level" : "Niveau de log", "Download logfile" : "Télécharger le fichier de journalisation", "More" : "Plus", "Less" : "Moins", diff --git a/settings/l10n/gl.js b/settings/l10n/gl.js index 0c03a5b06b3..633e877bd5a 100644 --- a/settings/l10n/gl.js +++ b/settings/l10n/gl.js @@ -174,7 +174,6 @@ OC.L10N.register( "Store credentials" : "Gardar as credenciais", "Test email settings" : "Correo de proba dos axustes", "Send email" : "Enviar o correo", - "Log level" : "Nivel de rexistro", "Download logfile" : "Descargar o ficheiro do rexistro", "More" : "Máis", "Less" : "Menos", diff --git a/settings/l10n/gl.json b/settings/l10n/gl.json index f2e924ac772..e8f78c560f2 100644 --- a/settings/l10n/gl.json +++ b/settings/l10n/gl.json @@ -172,7 +172,6 @@ "Store credentials" : "Gardar as credenciais", "Test email settings" : "Correo de proba dos axustes", "Send email" : "Enviar o correo", - "Log level" : "Nivel de rexistro", "Download logfile" : "Descargar o ficheiro do rexistro", "More" : "Máis", "Less" : "Menos", diff --git a/settings/l10n/he.js b/settings/l10n/he.js index 435f04cedd0..cfffdc8b967 100644 --- a/settings/l10n/he.js +++ b/settings/l10n/he.js @@ -41,7 +41,6 @@ OC.L10N.register( "Server address" : "כתובת שרת", "Port" : "פורט", "Credentials" : "פרטי גישה", - "Log level" : "רמת הדיווח", "More" : "יותר", "Less" : "פחות", "Version" : "גרסא", diff --git a/settings/l10n/he.json b/settings/l10n/he.json index 4df3810dec3..b38203e3d0e 100644 --- a/settings/l10n/he.json +++ b/settings/l10n/he.json @@ -39,7 +39,6 @@ "Server address" : "כתובת שרת", "Port" : "פורט", "Credentials" : "פרטי גישה", - "Log level" : "רמת הדיווח", "More" : "יותר", "Less" : "פחות", "Version" : "גרסא", diff --git a/settings/l10n/hr.js b/settings/l10n/hr.js index e32b8aa6608..d9c1bb3f4f9 100644 --- a/settings/l10n/hr.js +++ b/settings/l10n/hr.js @@ -111,7 +111,6 @@ OC.L10N.register( "SMTP Password" : "Lozinka SMPT", "Test email settings" : "Postavke za testnu e-poštu", "Send email" : "Pošaljite e-poštu", - "Log level" : "Razina zapisnika", "More" : "Više", "Less" : "Manje", "Version" : "Verzija", diff --git a/settings/l10n/hr.json b/settings/l10n/hr.json index 6cee1ef82aa..8867813b963 100644 --- a/settings/l10n/hr.json +++ b/settings/l10n/hr.json @@ -109,7 +109,6 @@ "SMTP Password" : "Lozinka SMPT", "Test email settings" : "Postavke za testnu e-poštu", "Send email" : "Pošaljite e-poštu", - "Log level" : "Razina zapisnika", "More" : "Više", "Less" : "Manje", "Version" : "Verzija", diff --git a/settings/l10n/hu_HU.js b/settings/l10n/hu_HU.js index 2cbcb3e822a..399129eda49 100644 --- a/settings/l10n/hu_HU.js +++ b/settings/l10n/hu_HU.js @@ -171,7 +171,6 @@ OC.L10N.register( "Store credentials" : "Azonosítók eltárolása", "Test email settings" : "Az e-mail beállítások ellenőrzése", "Send email" : "E-mail küldése", - "Log level" : "Naplózási szint", "Download logfile" : "Naplófájl letöltése", "More" : "Több", "Less" : "Kevesebb", diff --git a/settings/l10n/hu_HU.json b/settings/l10n/hu_HU.json index 44bebd90c4d..fe9f17f14ab 100644 --- a/settings/l10n/hu_HU.json +++ b/settings/l10n/hu_HU.json @@ -169,7 +169,6 @@ "Store credentials" : "Azonosítók eltárolása", "Test email settings" : "Az e-mail beállítások ellenőrzése", "Send email" : "E-mail küldése", - "Log level" : "Naplózási szint", "Download logfile" : "Naplófájl letöltése", "More" : "Több", "Less" : "Kevesebb", diff --git a/settings/l10n/id.js b/settings/l10n/id.js index d03f1b74453..e5efe797e69 100644 --- a/settings/l10n/id.js +++ b/settings/l10n/id.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Simpan kredensial", "Test email settings" : "Pengaturan email percobaan", "Send email" : "Kirim email", - "Log level" : "Level log", "Download logfile" : "Unduh berkas log", "More" : "Lainnya", "Less" : "Ciutkan", diff --git a/settings/l10n/id.json b/settings/l10n/id.json index c0d63bd9dce..8a30d825bc1 100644 --- a/settings/l10n/id.json +++ b/settings/l10n/id.json @@ -186,7 +186,6 @@ "Store credentials" : "Simpan kredensial", "Test email settings" : "Pengaturan email percobaan", "Send email" : "Kirim email", - "Log level" : "Level log", "Download logfile" : "Unduh berkas log", "More" : "Lainnya", "Less" : "Ciutkan", diff --git a/settings/l10n/it.js b/settings/l10n/it.js index 38684a67272..b01e4059e6d 100644 --- a/settings/l10n/it.js +++ b/settings/l10n/it.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Memorizza le credenziali", "Test email settings" : "Prova impostazioni email", "Send email" : "Invia email", - "Log level" : "Livello di log", "Download logfile" : "Scarica file di log", "More" : "Altro", "Less" : "Meno", diff --git a/settings/l10n/it.json b/settings/l10n/it.json index 11f65d07d22..1e9ae047bca 100644 --- a/settings/l10n/it.json +++ b/settings/l10n/it.json @@ -186,7 +186,6 @@ "Store credentials" : "Memorizza le credenziali", "Test email settings" : "Prova impostazioni email", "Send email" : "Invia email", - "Log level" : "Livello di log", "Download logfile" : "Scarica file di log", "More" : "Altro", "Less" : "Meno", diff --git a/settings/l10n/ja.js b/settings/l10n/ja.js index a1827392f86..6ebb5e96311 100644 --- a/settings/l10n/ja.js +++ b/settings/l10n/ja.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "資格情報を保存", "Test email settings" : "メール設定のテスト", "Send email" : "メールを送信", - "Log level" : "ログレベル", "Download logfile" : "ログファイルのダウンロード", "More" : "もっと見る", "Less" : "閉じる", diff --git a/settings/l10n/ja.json b/settings/l10n/ja.json index a2597c026fe..7a60706f723 100644 --- a/settings/l10n/ja.json +++ b/settings/l10n/ja.json @@ -186,7 +186,6 @@ "Store credentials" : "資格情報を保存", "Test email settings" : "メール設定のテスト", "Send email" : "メールを送信", - "Log level" : "ログレベル", "Download logfile" : "ログファイルのダウンロード", "More" : "もっと見る", "Less" : "閉じる", diff --git a/settings/l10n/ka_GE.js b/settings/l10n/ka_GE.js index ef91923ae2d..0c6ad6fd82d 100644 --- a/settings/l10n/ka_GE.js +++ b/settings/l10n/ka_GE.js @@ -41,7 +41,6 @@ OC.L10N.register( "Server address" : "სერვერის მისამართი", "Port" : "პორტი", "Credentials" : "იუზერ/პაროლი", - "Log level" : "ლოგირების დონე", "More" : "უფრო მეტი", "Less" : "უფრო ნაკლები", "Version" : "ვერსია", diff --git a/settings/l10n/ka_GE.json b/settings/l10n/ka_GE.json index e3414ed1996..5892c19547f 100644 --- a/settings/l10n/ka_GE.json +++ b/settings/l10n/ka_GE.json @@ -39,7 +39,6 @@ "Server address" : "სერვერის მისამართი", "Port" : "პორტი", "Credentials" : "იუზერ/პაროლი", - "Log level" : "ლოგირების დონე", "More" : "უფრო მეტი", "Less" : "უფრო ნაკლები", "Version" : "ვერსია", diff --git a/settings/l10n/km.js b/settings/l10n/km.js index 862763507a0..bba9783e9a0 100644 --- a/settings/l10n/km.js +++ b/settings/l10n/km.js @@ -56,7 +56,6 @@ OC.L10N.register( "Server address" : "អាសយដ្ឋាន​ម៉ាស៊ីន​បម្រើ", "Port" : "ច្រក", "Send email" : "ផ្ញើ​អ៊ីមែល", - "Log level" : "កម្រិត Log", "More" : "ច្រើន​ទៀត", "Less" : "តិច", "Version" : "កំណែ", diff --git a/settings/l10n/km.json b/settings/l10n/km.json index 3ba4b0784ee..89cd82da01a 100644 --- a/settings/l10n/km.json +++ b/settings/l10n/km.json @@ -54,7 +54,6 @@ "Server address" : "អាសយដ្ឋាន​ម៉ាស៊ីន​បម្រើ", "Port" : "ច្រក", "Send email" : "ផ្ញើ​អ៊ីមែល", - "Log level" : "កម្រិត Log", "More" : "ច្រើន​ទៀត", "Less" : "តិច", "Version" : "កំណែ", diff --git a/settings/l10n/kn.js b/settings/l10n/kn.js index f70cb0b3ce8..4ef7313b3bf 100644 --- a/settings/l10n/kn.js +++ b/settings/l10n/kn.js @@ -92,7 +92,6 @@ OC.L10N.register( "SMTP Password" : "SMTP ಗುಪ್ತ ಪದ", "Test email settings" : "ಪರೀರ್ಕ್ಷಾತ ಇ-ಅಂಚೆಯ ಆಯ್ಕೇ", "Send email" : "ಇ-ಅಂಚೆಯನ್ನು ಕಳುಹಿಸಿ", - "Log level" : "ಹಿನ್ನೆಲೆಯ ದಾಖಲೆಯ ಮಟ್ಟದ", "More" : "ಇನ್ನಷ್ಟು", "Less" : "ಕಡಿಮೆ", "Version" : "ಆವೃತ್ತಿ", diff --git a/settings/l10n/kn.json b/settings/l10n/kn.json index 54d5df31bc9..cbae632d1ce 100644 --- a/settings/l10n/kn.json +++ b/settings/l10n/kn.json @@ -90,7 +90,6 @@ "SMTP Password" : "SMTP ಗುಪ್ತ ಪದ", "Test email settings" : "ಪರೀರ್ಕ್ಷಾತ ಇ-ಅಂಚೆಯ ಆಯ್ಕೇ", "Send email" : "ಇ-ಅಂಚೆಯನ್ನು ಕಳುಹಿಸಿ", - "Log level" : "ಹಿನ್ನೆಲೆಯ ದಾಖಲೆಯ ಮಟ್ಟದ", "More" : "ಇನ್ನಷ್ಟು", "Less" : "ಕಡಿಮೆ", "Version" : "ಆವೃತ್ತಿ", diff --git a/settings/l10n/ko.js b/settings/l10n/ko.js index bba866b2d35..6eea3ecede7 100644 --- a/settings/l10n/ko.js +++ b/settings/l10n/ko.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "인증 정보 저장", "Test email settings" : "이메일 설정 시험", "Send email" : "이메일 보내기", - "Log level" : "로그 단계", "Download logfile" : "로그 파일 다운로드", "More" : "더 중요함", "Less" : "덜 중요함", diff --git a/settings/l10n/ko.json b/settings/l10n/ko.json index 7dc626b7702..1fb664b2138 100644 --- a/settings/l10n/ko.json +++ b/settings/l10n/ko.json @@ -186,7 +186,6 @@ "Store credentials" : "인증 정보 저장", "Test email settings" : "이메일 설정 시험", "Send email" : "이메일 보내기", - "Log level" : "로그 단계", "Download logfile" : "로그 파일 다운로드", "More" : "더 중요함", "Less" : "덜 중요함", diff --git a/settings/l10n/lt_LT.js b/settings/l10n/lt_LT.js index 2b739db71c9..b54d9cad1fc 100644 --- a/settings/l10n/lt_LT.js +++ b/settings/l10n/lt_LT.js @@ -63,7 +63,6 @@ OC.L10N.register( "Authentication required" : "Reikalinga autentikacija", "Server address" : "Serverio adresas", "Port" : "Prievadas", - "Log level" : "Žurnalo išsamumas", "More" : "Daugiau", "Less" : "Mažiau", "Version" : "Versija", diff --git a/settings/l10n/lt_LT.json b/settings/l10n/lt_LT.json index a8cd70f7dd6..6142e8a7158 100644 --- a/settings/l10n/lt_LT.json +++ b/settings/l10n/lt_LT.json @@ -61,7 +61,6 @@ "Authentication required" : "Reikalinga autentikacija", "Server address" : "Serverio adresas", "Port" : "Prievadas", - "Log level" : "Žurnalo išsamumas", "More" : "Daugiau", "Less" : "Mažiau", "Version" : "Versija", diff --git a/settings/l10n/lv.js b/settings/l10n/lv.js index b84b57dd315..30cb20b6452 100644 --- a/settings/l10n/lv.js +++ b/settings/l10n/lv.js @@ -112,7 +112,6 @@ OC.L10N.register( "SMTP Password" : "SMTP parole", "Test email settings" : "Izmēģināt e-pasta iestatījumus", "Send email" : "Sūtīt e-pastu", - "Log level" : "Žurnāla līmenis", "More" : "Vairāk", "Less" : "Mazāk", "Version" : "Versija", diff --git a/settings/l10n/lv.json b/settings/l10n/lv.json index 23172d90b8e..18b41b82f97 100644 --- a/settings/l10n/lv.json +++ b/settings/l10n/lv.json @@ -110,7 +110,6 @@ "SMTP Password" : "SMTP parole", "Test email settings" : "Izmēģināt e-pasta iestatījumus", "Send email" : "Sūtīt e-pastu", - "Log level" : "Žurnāla līmenis", "More" : "Vairāk", "Less" : "Mazāk", "Version" : "Versija", diff --git a/settings/l10n/mk.js b/settings/l10n/mk.js index f4ce5676543..65e9d4c09a8 100644 --- a/settings/l10n/mk.js +++ b/settings/l10n/mk.js @@ -103,7 +103,6 @@ OC.L10N.register( "SMTP Password" : "SMTP лозинка", "Test email settings" : "Провери ги нагодувањаа за електронска пошта", "Send email" : "Испрати пошта", - "Log level" : "Ниво на логирање", "More" : "Повеќе", "Less" : "Помалку", "Version" : "Верзија", diff --git a/settings/l10n/mk.json b/settings/l10n/mk.json index c93ae59e35c..607808c7367 100644 --- a/settings/l10n/mk.json +++ b/settings/l10n/mk.json @@ -101,7 +101,6 @@ "SMTP Password" : "SMTP лозинка", "Test email settings" : "Провери ги нагодувањаа за електронска пошта", "Send email" : "Испрати пошта", - "Log level" : "Ниво на логирање", "More" : "Повеќе", "Less" : "Помалку", "Version" : "Верзија", diff --git a/settings/l10n/ms_MY.js b/settings/l10n/ms_MY.js index 8bdb9b3878c..db26c502d3e 100644 --- a/settings/l10n/ms_MY.js +++ b/settings/l10n/ms_MY.js @@ -14,7 +14,6 @@ OC.L10N.register( "__language_name__" : "_nama_bahasa_", "Login" : "Log masuk", "Server address" : "Alamat pelayan", - "Log level" : "Tahap Log", "More" : "Lanjutan", "by" : "oleh", "Password" : "Kata laluan", diff --git a/settings/l10n/ms_MY.json b/settings/l10n/ms_MY.json index 4547f0a32b5..342d679ecb4 100644 --- a/settings/l10n/ms_MY.json +++ b/settings/l10n/ms_MY.json @@ -12,7 +12,6 @@ "__language_name__" : "_nama_bahasa_", "Login" : "Log masuk", "Server address" : "Alamat pelayan", - "Log level" : "Tahap Log", "More" : "Lanjutan", "by" : "oleh", "Password" : "Kata laluan", diff --git a/settings/l10n/nb_NO.js b/settings/l10n/nb_NO.js index 44585ece158..0cea17dbb48 100644 --- a/settings/l10n/nb_NO.js +++ b/settings/l10n/nb_NO.js @@ -187,7 +187,6 @@ OC.L10N.register( "Store credentials" : "Lagre påloggingsdetaljer", "Test email settings" : "Test innstillinger for e-post", "Send email" : "Send e-post", - "Log level" : "Loggnivå", "Download logfile" : "Last ned loggfil", "More" : "Mer", "Less" : "Mindre", diff --git a/settings/l10n/nb_NO.json b/settings/l10n/nb_NO.json index 2cd023b3ac8..0eca73177d3 100644 --- a/settings/l10n/nb_NO.json +++ b/settings/l10n/nb_NO.json @@ -185,7 +185,6 @@ "Store credentials" : "Lagre påloggingsdetaljer", "Test email settings" : "Test innstillinger for e-post", "Send email" : "Send e-post", - "Log level" : "Loggnivå", "Download logfile" : "Last ned loggfil", "More" : "Mer", "Less" : "Mindre", diff --git a/settings/l10n/nl.js b/settings/l10n/nl.js index 9b4aff943f2..4f8fb58f53a 100644 --- a/settings/l10n/nl.js +++ b/settings/l10n/nl.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Opslaan inloggegevens", "Test email settings" : "Test e-mailinstellingen", "Send email" : "Versturen e-mail", - "Log level" : "Log niveau", "Download logfile" : "Download logbestand", "More" : "Meer", "Less" : "Minder", diff --git a/settings/l10n/nl.json b/settings/l10n/nl.json index 14cea3dcb63..dc4f66e406d 100644 --- a/settings/l10n/nl.json +++ b/settings/l10n/nl.json @@ -186,7 +186,6 @@ "Store credentials" : "Opslaan inloggegevens", "Test email settings" : "Test e-mailinstellingen", "Send email" : "Versturen e-mail", - "Log level" : "Log niveau", "Download logfile" : "Download logbestand", "More" : "Meer", "Less" : "Minder", diff --git a/settings/l10n/nn_NO.js b/settings/l10n/nn_NO.js index fb3c45debb4..7539ca7f099 100644 --- a/settings/l10n/nn_NO.js +++ b/settings/l10n/nn_NO.js @@ -47,7 +47,6 @@ OC.L10N.register( "Execute one task with each page loaded" : "Utfør éi oppgåve for kvar sidelasting", "Encryption" : "Kryptering", "Server address" : "Tenaradresse", - "Log level" : "Log nivå", "More" : "Meir", "Less" : "Mindre", "Version" : "Utgåve", diff --git a/settings/l10n/nn_NO.json b/settings/l10n/nn_NO.json index b1bcc62ea32..8d30f4c3612 100644 --- a/settings/l10n/nn_NO.json +++ b/settings/l10n/nn_NO.json @@ -45,7 +45,6 @@ "Execute one task with each page loaded" : "Utfør éi oppgåve for kvar sidelasting", "Encryption" : "Kryptering", "Server address" : "Tenaradresse", - "Log level" : "Log nivå", "More" : "Meir", "Less" : "Mindre", "Version" : "Utgåve", diff --git a/settings/l10n/oc.js b/settings/l10n/oc.js index 70c66652e42..38055739443 100644 --- a/settings/l10n/oc.js +++ b/settings/l10n/oc.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Enregistrar los identificants", "Test email settings" : "Testar los paramètres e-mail", "Send email" : "Mandar un mail", - "Log level" : "Nivèl de log", "Download logfile" : "Telecargar lo fichièr de jornalizacion", "More" : "Mai", "Less" : "Mens", diff --git a/settings/l10n/oc.json b/settings/l10n/oc.json index a7e987f9787..e60cfb45ed3 100644 --- a/settings/l10n/oc.json +++ b/settings/l10n/oc.json @@ -186,7 +186,6 @@ "Store credentials" : "Enregistrar los identificants", "Test email settings" : "Testar los paramètres e-mail", "Send email" : "Mandar un mail", - "Log level" : "Nivèl de log", "Download logfile" : "Telecargar lo fichièr de jornalizacion", "More" : "Mai", "Less" : "Mens", diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js index 86108df8f01..862d56fc848 100644 --- a/settings/l10n/pl.js +++ b/settings/l10n/pl.js @@ -134,7 +134,6 @@ OC.L10N.register( "Store credentials" : "Zapisz poświadczenia", "Test email settings" : "Ustawienia testowej wiadomości", "Send email" : "Wyślij email", - "Log level" : "Poziom logów", "Download logfile" : "Pobierz plik log", "More" : "Więcej", "Less" : "Mniej", diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json index f84a6214abc..db527fa4517 100644 --- a/settings/l10n/pl.json +++ b/settings/l10n/pl.json @@ -132,7 +132,6 @@ "Store credentials" : "Zapisz poświadczenia", "Test email settings" : "Ustawienia testowej wiadomości", "Send email" : "Wyślij email", - "Log level" : "Poziom logów", "Download logfile" : "Pobierz plik log", "More" : "Więcej", "Less" : "Mniej", diff --git a/settings/l10n/pt_BR.js b/settings/l10n/pt_BR.js index 9caeb6169ad..1e33ffb10cc 100644 --- a/settings/l10n/pt_BR.js +++ b/settings/l10n/pt_BR.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Armazenar credenciais", "Test email settings" : "Configurações de e-mail de teste", "Send email" : "Enviar email", - "Log level" : "Nível de registro", "Download logfile" : "Baixar o arquivo de log", "More" : "Mais", "Less" : "Menos", diff --git a/settings/l10n/pt_BR.json b/settings/l10n/pt_BR.json index 52072f8f1fa..eaaf84d3739 100644 --- a/settings/l10n/pt_BR.json +++ b/settings/l10n/pt_BR.json @@ -186,7 +186,6 @@ "Store credentials" : "Armazenar credenciais", "Test email settings" : "Configurações de e-mail de teste", "Send email" : "Enviar email", - "Log level" : "Nível de registro", "Download logfile" : "Baixar o arquivo de log", "More" : "Mais", "Less" : "Menos", diff --git a/settings/l10n/pt_PT.js b/settings/l10n/pt_PT.js index c964856142f..b0f25796901 100644 --- a/settings/l10n/pt_PT.js +++ b/settings/l10n/pt_PT.js @@ -165,7 +165,6 @@ OC.L10N.register( "Store credentials" : "Armazenar credenciais", "Test email settings" : "Testar definições de e-mail", "Send email" : "Enviar email", - "Log level" : "Nível do registo", "Download logfile" : "Descarregar logfile", "More" : "Mais", "Less" : "Menos", diff --git a/settings/l10n/pt_PT.json b/settings/l10n/pt_PT.json index 53a9da55517..4df54b81008 100644 --- a/settings/l10n/pt_PT.json +++ b/settings/l10n/pt_PT.json @@ -163,7 +163,6 @@ "Store credentials" : "Armazenar credenciais", "Test email settings" : "Testar definições de e-mail", "Send email" : "Enviar email", - "Log level" : "Nível do registo", "Download logfile" : "Descarregar logfile", "More" : "Mais", "Less" : "Menos", diff --git a/settings/l10n/ro.js b/settings/l10n/ro.js index b969fae1b60..354c45092b7 100644 --- a/settings/l10n/ro.js +++ b/settings/l10n/ro.js @@ -82,7 +82,6 @@ OC.L10N.register( "SMTP Password" : "Parolă SMTP", "Test email settings" : "Verifică setările de e-mail", "Send email" : "Expediază mesajul", - "Log level" : "Nivel jurnal", "More" : "Mai mult", "Less" : "Mai puțin", "Version" : "Versiunea", diff --git a/settings/l10n/ro.json b/settings/l10n/ro.json index 83c2572901d..05a736d9fdf 100644 --- a/settings/l10n/ro.json +++ b/settings/l10n/ro.json @@ -80,7 +80,6 @@ "SMTP Password" : "Parolă SMTP", "Test email settings" : "Verifică setările de e-mail", "Send email" : "Expediază mesajul", - "Log level" : "Nivel jurnal", "More" : "Mai mult", "Less" : "Mai puțin", "Version" : "Versiunea", diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js index ab6621483a5..a6f62fd5e9f 100644 --- a/settings/l10n/ru.js +++ b/settings/l10n/ru.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "Сохранить учётные данные", "Test email settings" : "Проверить настройки почты", "Send email" : "Отправить email", - "Log level" : "Уровень детализации журнала", "Download logfile" : "Скачать журнал", "More" : "Больше", "Less" : "Меньше", diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json index 21bb4044ba2..4ecc1dd6195 100644 --- a/settings/l10n/ru.json +++ b/settings/l10n/ru.json @@ -186,7 +186,6 @@ "Store credentials" : "Сохранить учётные данные", "Test email settings" : "Проверить настройки почты", "Send email" : "Отправить email", - "Log level" : "Уровень детализации журнала", "Download logfile" : "Скачать журнал", "More" : "Больше", "Less" : "Меньше", diff --git a/settings/l10n/sk_SK.js b/settings/l10n/sk_SK.js index 66332871bb0..2de64dd5a56 100644 --- a/settings/l10n/sk_SK.js +++ b/settings/l10n/sk_SK.js @@ -160,7 +160,6 @@ OC.L10N.register( "Store credentials" : "Ukladať prihlasovacie údaje", "Test email settings" : "Nastavenia testovacieho emailu", "Send email" : "Odoslať email", - "Log level" : "Úroveň záznamu", "Download logfile" : "Stiahnuť súbor logu", "More" : "Viac", "Less" : "Menej", diff --git a/settings/l10n/sk_SK.json b/settings/l10n/sk_SK.json index 6cfe691ee75..2fc4064a033 100644 --- a/settings/l10n/sk_SK.json +++ b/settings/l10n/sk_SK.json @@ -158,7 +158,6 @@ "Store credentials" : "Ukladať prihlasovacie údaje", "Test email settings" : "Nastavenia testovacieho emailu", "Send email" : "Odoslať email", - "Log level" : "Úroveň záznamu", "Download logfile" : "Stiahnuť súbor logu", "More" : "Viac", "Less" : "Menej", diff --git a/settings/l10n/sl.js b/settings/l10n/sl.js index 1e436f7b81a..71525285a4e 100644 --- a/settings/l10n/sl.js +++ b/settings/l10n/sl.js @@ -151,7 +151,6 @@ OC.L10N.register( "Store credentials" : "Shrani poverila", "Test email settings" : "Preizkus nastavitev elektronske pošte", "Send email" : "Pošlji elektronsko sporočilo", - "Log level" : "Raven beleženja", "Download logfile" : "Prejmi dnevniško datoteko", "More" : "Več", "Less" : "Manj", diff --git a/settings/l10n/sl.json b/settings/l10n/sl.json index 6af0302af6a..65470f9c193 100644 --- a/settings/l10n/sl.json +++ b/settings/l10n/sl.json @@ -149,7 +149,6 @@ "Store credentials" : "Shrani poverila", "Test email settings" : "Preizkus nastavitev elektronske pošte", "Send email" : "Pošlji elektronsko sporočilo", - "Log level" : "Raven beleženja", "Download logfile" : "Prejmi dnevniško datoteko", "More" : "Več", "Less" : "Manj", diff --git a/settings/l10n/sq.js b/settings/l10n/sq.js index 56a0a142f07..fc7f21390ec 100644 --- a/settings/l10n/sq.js +++ b/settings/l10n/sq.js @@ -184,7 +184,6 @@ OC.L10N.register( "Store credentials" : "Depozitoji kredencialet", "Test email settings" : "Testoni rregullimet e email-it", "Send email" : "Dërgo email", - "Log level" : "Shkallë regjistrimi", "Download logfile" : "Shkarkoni kartelën regjistër", "More" : "Më tepër", "Less" : "Më pak", diff --git a/settings/l10n/sq.json b/settings/l10n/sq.json index eb5f05106a4..912b93e3fe1 100644 --- a/settings/l10n/sq.json +++ b/settings/l10n/sq.json @@ -182,7 +182,6 @@ "Store credentials" : "Depozitoji kredencialet", "Test email settings" : "Testoni rregullimet e email-it", "Send email" : "Dërgo email", - "Log level" : "Shkallë regjistrimi", "Download logfile" : "Shkarkoni kartelën regjistër", "More" : "Më tepër", "Less" : "Më pak", diff --git a/settings/l10n/sr.js b/settings/l10n/sr.js index 28c61337eb8..3a3bc293473 100644 --- a/settings/l10n/sr.js +++ b/settings/l10n/sr.js @@ -171,7 +171,6 @@ OC.L10N.register( "Store credentials" : "Сачувај акредитиве", "Test email settings" : "Тестирај поставке е-поште", "Send email" : "Пошаљи е-пошту", - "Log level" : "Ниво бележења", "Download logfile" : "Преузми записник", "More" : "Више", "Less" : "Мање", diff --git a/settings/l10n/sr.json b/settings/l10n/sr.json index 2aff5a9d2b2..5003066df7b 100644 --- a/settings/l10n/sr.json +++ b/settings/l10n/sr.json @@ -169,7 +169,6 @@ "Store credentials" : "Сачувај акредитиве", "Test email settings" : "Тестирај поставке е-поште", "Send email" : "Пошаљи е-пошту", - "Log level" : "Ниво бележења", "Download logfile" : "Преузми записник", "More" : "Више", "Less" : "Мање", diff --git a/settings/l10n/sv.js b/settings/l10n/sv.js index 43c6bf06218..6ba223cb563 100644 --- a/settings/l10n/sv.js +++ b/settings/l10n/sv.js @@ -132,7 +132,6 @@ OC.L10N.register( "Store credentials" : "Lagra inloggningsuppgifter", "Test email settings" : "Testa e-postinställningar", "Send email" : "Skicka e-post", - "Log level" : "Nivå på loggning", "Download logfile" : "Ladda ner loggfil", "More" : "Mer", "Less" : "Mindre", diff --git a/settings/l10n/sv.json b/settings/l10n/sv.json index 3e61a6e9650..00d4811a846 100644 --- a/settings/l10n/sv.json +++ b/settings/l10n/sv.json @@ -130,7 +130,6 @@ "Store credentials" : "Lagra inloggningsuppgifter", "Test email settings" : "Testa e-postinställningar", "Send email" : "Skicka e-post", - "Log level" : "Nivå på loggning", "Download logfile" : "Ladda ner loggfil", "More" : "Mer", "Less" : "Mindre", diff --git a/settings/l10n/th_TH.js b/settings/l10n/th_TH.js index d4de49436b0..9bd86f5a81a 100644 --- a/settings/l10n/th_TH.js +++ b/settings/l10n/th_TH.js @@ -188,7 +188,6 @@ OC.L10N.register( "Store credentials" : "ข้อมูลประจำตัวของร้านค้า", "Test email settings" : "การตั้งค่าอีเมลทดสอบ", "Send email" : "ส่งอีเมล", - "Log level" : "ระดับการเก็บบันทึก log", "Download logfile" : "ดาวน์โหลดไฟล์บันทึก", "More" : "มาก", "Less" : "น้อย", diff --git a/settings/l10n/th_TH.json b/settings/l10n/th_TH.json index f365ca49746..001f09f89fe 100644 --- a/settings/l10n/th_TH.json +++ b/settings/l10n/th_TH.json @@ -186,7 +186,6 @@ "Store credentials" : "ข้อมูลประจำตัวของร้านค้า", "Test email settings" : "การตั้งค่าอีเมลทดสอบ", "Send email" : "ส่งอีเมล", - "Log level" : "ระดับการเก็บบันทึก log", "Download logfile" : "ดาวน์โหลดไฟล์บันทึก", "More" : "มาก", "Less" : "น้อย", diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js index a3cec1f93fd..4c60ee3d072 100644 --- a/settings/l10n/tr.js +++ b/settings/l10n/tr.js @@ -181,7 +181,6 @@ OC.L10N.register( "Store credentials" : "Kimlik bilgilerini depola", "Test email settings" : "E-posta ayarlarını sına", "Send email" : "E-posta gönder", - "Log level" : "Günlük seviyesi", "Download logfile" : "Günlük dosyasını indir", "More" : "Daha fazla", "Less" : "Daha az", diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json index 6a0e6f7bff4..c7de4a505fb 100644 --- a/settings/l10n/tr.json +++ b/settings/l10n/tr.json @@ -179,7 +179,6 @@ "Store credentials" : "Kimlik bilgilerini depola", "Test email settings" : "E-posta ayarlarını sına", "Send email" : "E-posta gönder", - "Log level" : "Günlük seviyesi", "Download logfile" : "Günlük dosyasını indir", "More" : "Daha fazla", "Less" : "Daha az", diff --git a/settings/l10n/ug.js b/settings/l10n/ug.js index 56fc4fb1a89..fafe6cf559d 100644 --- a/settings/l10n/ug.js +++ b/settings/l10n/ug.js @@ -32,7 +32,6 @@ OC.L10N.register( "Encryption" : "شىفىرلاش", "Server address" : "مۇلازىمېتىر ئادرىسى", "Port" : "ئېغىز", - "Log level" : "خاتىرە دەرىجىسى", "More" : "تېخىمۇ كۆپ", "Less" : "ئاز", "Version" : "نەشرى", diff --git a/settings/l10n/ug.json b/settings/l10n/ug.json index 149ae1c08c1..f81f82ab704 100644 --- a/settings/l10n/ug.json +++ b/settings/l10n/ug.json @@ -30,7 +30,6 @@ "Encryption" : "شىفىرلاش", "Server address" : "مۇلازىمېتىر ئادرىسى", "Port" : "ئېغىز", - "Log level" : "خاتىرە دەرىجىسى", "More" : "تېخىمۇ كۆپ", "Less" : "ئاز", "Version" : "نەشرى", diff --git a/settings/l10n/uk.js b/settings/l10n/uk.js index 0c98817594c..2775efd8fa9 100644 --- a/settings/l10n/uk.js +++ b/settings/l10n/uk.js @@ -169,7 +169,6 @@ OC.L10N.register( "Store credentials" : "Зберігати облікові дані", "Test email settings" : "Тестувати налаштування електронної пошти", "Send email" : "Надіслати листа", - "Log level" : "Рівень протоколювання", "Download logfile" : "Завантажити файл журналу", "More" : "Більше", "Less" : "Менше", diff --git a/settings/l10n/uk.json b/settings/l10n/uk.json index c9378c70b16..d2a594fffc0 100644 --- a/settings/l10n/uk.json +++ b/settings/l10n/uk.json @@ -167,7 +167,6 @@ "Store credentials" : "Зберігати облікові дані", "Test email settings" : "Тестувати налаштування електронної пошти", "Send email" : "Надіслати листа", - "Log level" : "Рівень протоколювання", "Download logfile" : "Завантажити файл журналу", "More" : "Більше", "Less" : "Менше", diff --git a/settings/l10n/zh_CN.js b/settings/l10n/zh_CN.js index a1f828172d4..4730cba46d7 100644 --- a/settings/l10n/zh_CN.js +++ b/settings/l10n/zh_CN.js @@ -180,7 +180,6 @@ OC.L10N.register( "Store credentials" : "存储凭据", "Test email settings" : "测试电子邮件设置", "Send email" : "发送邮件", - "Log level" : "日志级别", "Download logfile" : "下载日志文件", "More" : "更多", "Less" : "更少", diff --git a/settings/l10n/zh_CN.json b/settings/l10n/zh_CN.json index 9cb1c97b9d6..69d6dbf014e 100644 --- a/settings/l10n/zh_CN.json +++ b/settings/l10n/zh_CN.json @@ -178,7 +178,6 @@ "Store credentials" : "存储凭据", "Test email settings" : "测试电子邮件设置", "Send email" : "发送邮件", - "Log level" : "日志级别", "Download logfile" : "下载日志文件", "More" : "更多", "Less" : "更少", diff --git a/settings/l10n/zh_HK.js b/settings/l10n/zh_HK.js index c2d56692bcf..98445b9c961 100644 --- a/settings/l10n/zh_HK.js +++ b/settings/l10n/zh_HK.js @@ -32,7 +32,6 @@ OC.L10N.register( "Port" : "連接埠", "SMTP Username" : "SMTP 使用者名稱", "SMTP Password" : "SMTP 密碼", - "Log level" : "日誌等級", "More" : "更多", "Version" : "版本", "Forum" : "討論區", diff --git a/settings/l10n/zh_HK.json b/settings/l10n/zh_HK.json index 4a5e3ed713a..2f24b442cc6 100644 --- a/settings/l10n/zh_HK.json +++ b/settings/l10n/zh_HK.json @@ -30,7 +30,6 @@ "Port" : "連接埠", "SMTP Username" : "SMTP 使用者名稱", "SMTP Password" : "SMTP 密碼", - "Log level" : "日誌等級", "More" : "更多", "Version" : "版本", "Forum" : "討論區", diff --git a/settings/l10n/zh_TW.js b/settings/l10n/zh_TW.js index b59605da676..e863891e042 100644 --- a/settings/l10n/zh_TW.js +++ b/settings/l10n/zh_TW.js @@ -186,7 +186,6 @@ OC.L10N.register( "Store credentials" : "儲存帳密", "Test email settings" : "測試郵件設定", "Send email" : "寄送郵件", - "Log level" : "紀錄層級", "Download logfile" : "下載記錄檔", "More" : "更多", "Less" : "更少", diff --git a/settings/l10n/zh_TW.json b/settings/l10n/zh_TW.json index 9e1e42455df..312d93ea258 100644 --- a/settings/l10n/zh_TW.json +++ b/settings/l10n/zh_TW.json @@ -184,7 +184,6 @@ "Store credentials" : "儲存帳密", "Test email settings" : "測試郵件設定", "Send email" : "寄送郵件", - "Log level" : "紀錄層級", "Download logfile" : "下載記錄檔", "More" : "更多", "Less" : "更少", -- GitLab From e733244148a3b1e228caf8c07aef15893073058a Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Thu, 19 Nov 2015 22:03:10 +0100 Subject: [PATCH 103/344] Bump 3rdparty. No longer ship tests dirs --- 3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index 5c7b1870477..f631b28b350 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 5c7b18704773473f8f7846ef942fc958f449c977 +Subproject commit f631b28b350b2e69b8cb47ac51735b8a8266c0fb -- GitLab From dd10e1d538e91bdebad0c250a62d06afe9d74b55 Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Fri, 20 Nov 2015 09:17:48 +0000 Subject: [PATCH 104/344] modified makedavrequest to return response --- build/integration/features/bootstrap/FeatureContext.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 329b18d151c..3a4b619fe7a 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -918,7 +918,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { foreach ($headers as $key => $value) { $request->addHeader($key, $value); } - $this->response = $client->send($request); + //$this->response = $client->send($request); + return $client->send($request); } /** @@ -927,7 +928,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function userMovedFile($user, $fileSource, $fileDestination){ $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav"; $headers['Destination'] = $fullUrl . $fileDestination; - $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); PHPUnit_Framework_Assert::assertEquals(201, $this->response->getStatusCode()); } @@ -937,7 +938,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { public function userMovesFile($user, $fileSource, $fileDestination){ $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav"; $headers['Destination'] = $fullUrl . $fileDestination; - $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); } /** -- GitLab From a2938385f9f5d585eacdbe15791b913614c94f9d Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Fri, 20 Nov 2015 11:26:52 +0000 Subject: [PATCH 105/344] Making webdav path configurable --- .../features/bootstrap/FeatureContext.php | 16 +++++++++++++--- build/integration/features/sharing-v1.feature | 1 + .../integration/features/webdav-related.feature | 15 +++++++++------ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 3a4b619fe7a..b3d928bb21d 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -27,6 +27,9 @@ class FeatureContext implements Context, SnippetAcceptingContext { /** @var int */ private $sharingApiVersion = 1; + /** @var string*/ + private $davPath = "remote.php/webdav"; + /** @var SimpleXMLElement */ private $lastShareData = null; @@ -211,6 +214,13 @@ class FeatureContext implements Context, SnippetAcceptingContext { $this->apiVersion = $version; } + /** + * @Given /^using dav path "([^"]*)"$/ + */ + public function usingDavPath($davPath) { + $this->davPath = $davPath; + } + /** * @Given /^user "([^"]*)" exists$/ */ @@ -906,7 +916,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { } public function makeDavRequest($user, $method, $path, $headers){ - $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav" . "$path"; + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath . "$path"; $client = new Client(); $options = []; if ($user === 'admin') { @@ -926,7 +936,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { * @Given /^User "([^"]*)" moved file "([^"]*)" to "([^"]*)"$/ */ public function userMovedFile($user, $fileSource, $fileDestination){ - $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav"; + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath; $headers['Destination'] = $fullUrl . $fileDestination; $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); PHPUnit_Framework_Assert::assertEquals(201, $this->response->getStatusCode()); @@ -936,7 +946,7 @@ class FeatureContext implements Context, SnippetAcceptingContext { * @When /^User "([^"]*)" moves file "([^"]*)" to "([^"]*)"$/ */ public function userMovesFile($user, $fileSource, $fileDestination){ - $fullUrl = substr($this->baseUrl, 0, -4) . "remote.php/webdav"; + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath; $headers['Destination'] = $fullUrl . $fileDestination; $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); } diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 0d64fcd8bcb..33085866bf4 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -1,6 +1,7 @@ Feature: sharing Background: Given using api version "1" + Given using dav path "remote.php/webdav" Scenario: Creating a new share with user Given user "user0" exists diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index 450065ded2d..27d354644d0 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -1,12 +1,15 @@ Feature: sharing Background: - Given using api version "1" + Given using api version "1" + + Scenario: moving a file old way + Given using dav path "remote.php/webdav" + And As an "admin" + And user "user0" exists + When User "user0" moves file "/textfile0.txt" to "/FOLDER/textfile0.txt" + Then the HTTP status code should be "201" + - Scenario: moving a file - Given As an "admin" - And user "user0" exists - When User "user0" moves file "/textfile0.txt" to "/FOLDER/textfile0.txt" - Then the HTTP status code should be "201" -- GitLab From 69a03c2e60fce7e64baac1659af71cb4b0af0d76 Mon Sep 17 00:00:00 2001 From: Sergio Bertolin Date: Fri, 20 Nov 2015 11:56:05 +0000 Subject: [PATCH 106/344] Added test case about trying to reshare a file with more permissions --- build/integration/features/sharing-v1.feature | 19 +++++++++++++++++++ .../features/webdav-related.feature | 18 +++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 33085866bf4..063a40b1d3c 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -333,6 +333,25 @@ Feature: sharing Then the OCS status code should be "404" And the HTTP status code should be "200" + Scenario: User is not allowed to reshare file with more permissions + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /textfile0.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 16 | + And As an "user1" + When creating a share with + | path | /textfile0. (2).txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" Scenario: Delete all group shares Given As an "admin" diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index 27d354644d0..961b6b03431 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -1,13 +1,13 @@ Feature: sharing - Background: - Given using api version "1" - - Scenario: moving a file old way - Given using dav path "remote.php/webdav" - And As an "admin" - And user "user0" exists - When User "user0" moves file "/textfile0.txt" to "/FOLDER/textfile0.txt" - Then the HTTP status code should be "201" + Background: + Given using api version "1" + + Scenario: moving a file old way + Given using dav path "remote.php/webdav" + And As an "admin" + And user "user0" exists + When User "user0" moves file "/textfile0.txt" to "/FOLDER/textfile0.txt" + Then the HTTP status code should be "201" -- GitLab From c86483f3edb931d58477e4003490fb02fee6369f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 20 Nov 2015 14:38:29 +0100 Subject: [PATCH 107/344] Adjust PHPDoc as suggested --- lib/private/group.php | 2 +- lib/private/group/manager.php | 2 +- lib/public/igroupmanager.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/private/group.php b/lib/private/group.php index 4eed2a85450..fdf8086f1e8 100644 --- a/lib/private/group.php +++ b/lib/private/group.php @@ -183,7 +183,7 @@ class OC_Group { * * This function fetches all groups a user belongs to. It does not check * if the user exists at all. - * @deprecated Use \OC::$server->getGroupManager->getuserGroupIds($user) + * @deprecated Use \OC::$server->getGroupManager->getUserGroupIds($user) */ public static function getUserGroups($uid) { $user = self::getUserManager()->get($uid); diff --git a/lib/private/group/manager.php b/lib/private/group/manager.php index 40018370af5..7387b423643 100644 --- a/lib/private/group/manager.php +++ b/lib/private/group/manager.php @@ -210,7 +210,7 @@ class Manager extends PublicEmitter implements IGroupManager { } /** - * @param \OC\User\User $user + * @param \OC\User\User|null $user * @return \OC\Group\Group[] */ public function getUserGroups($user) { diff --git a/lib/public/igroupmanager.php b/lib/public/igroupmanager.php index 862c77218de..da80cfdd374 100644 --- a/lib/public/igroupmanager.php +++ b/lib/public/igroupmanager.php @@ -93,7 +93,7 @@ interface IGroupManager { public function search($search, $limit = null, $offset = null); /** - * @param \OCP\IUser $user + * @param \OCP\IUser|null $user * @return \OCP\IGroup[] * @since 8.0.0 */ -- GitLab From 90ff4641e778f9825047194872bc2dca3344e7b8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 20 Nov 2015 15:23:09 +0100 Subject: [PATCH 108/344] dont die if the external storage backend doesn't exist --- .../service/storagesservice.php | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/apps/files_external/service/storagesservice.php b/apps/files_external/service/storagesservice.php index 41bb0ca9b80..3446ed0dab3 100644 --- a/apps/files_external/service/storagesservice.php +++ b/apps/files_external/service/storagesservice.php @@ -221,17 +221,26 @@ abstract class StoragesService { $currentStorage->setMountPoint($relativeMountPath); } - $this->populateStorageConfigWithLegacyOptions( - $currentStorage, - $mountType, - $applicable, - $storageOptions - ); - - if ($hasId) { - $storages[$configId] = $currentStorage; - } else { - $storagesWithConfigHash[$configId] = $currentStorage; + try { + $this->populateStorageConfigWithLegacyOptions( + $currentStorage, + $mountType, + $applicable, + $storageOptions + ); + + if ($hasId) { + $storages[$configId] = $currentStorage; + } else { + $storagesWithConfigHash[$configId] = $currentStorage; + } + } catch (\UnexpectedValueException $e) { + // dont die if a storage backend doesn't exist + \OCP\Util::writeLog( + 'files_external', + 'Could not load storage: "' . $e->getMessage() . '"', + \OCP\Util::ERROR + ); } } } -- GitLab From a63a1043b6a40193a44d2fb1b702a775bb761c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 19 Nov 2015 17:49:43 +0100 Subject: [PATCH 109/344] unit tests --- .../backgroundjob/getsharedsecret.php | 14 +- .../backgroundjob/requestsharedsecret.php | 10 +- apps/federation/lib/dbhandler.php | 4 +- .../backgroundjob/getsharedsecrettest.php | 190 ++++++++++++++++++ .../backgroundjob/requestsharedsecrettest.php | 169 ++++++++++++++++ apps/federation/tests/lib/dbhandlertest.php | 108 +++++++++- .../tests/lib/trustedserverstest.php | 71 ++++++- 7 files changed, 549 insertions(+), 17 deletions(-) create mode 100644 apps/federation/tests/backgroundjob/getsharedsecrettest.php create mode 100644 apps/federation/tests/backgroundjob/requestsharedsecrettest.php diff --git a/apps/federation/backgroundjob/getsharedsecret.php b/apps/federation/backgroundjob/getsharedsecret.php index 88f2a51045a..eb55fa2d6ab 100644 --- a/apps/federation/backgroundjob/getsharedsecret.php +++ b/apps/federation/backgroundjob/getsharedsecret.php @@ -110,10 +110,20 @@ class GetSharedSecret extends QueuedJob{ $target = $this->argument['url']; // only execute if target is still in the list of trusted domains if ($this->trustedServers->isTrustedServer($target)) { - parent::execute($jobList, $logger); + $this->parentExecute($jobList, $logger); } } + /** + * call execute() method of parent + * + * @param JobList $jobList + * @param ILogger $logger + */ + protected function parentExecute($jobList, $logger) { + parent::execute($jobList, $logger); + } + protected function run($argument) { $target = $argument['url']; $source = $this->urlGenerator->getAbsoluteURL('/'); @@ -146,7 +156,7 @@ class GetSharedSecret extends QueuedJob{ && $status !== Http::STATUS_FORBIDDEN ) { $this->jobList->add( - 'OCA\Federation\Backgroundjob\GetSharedSecret', + 'OCA\Federation\BackgroundJob\GetSharedSecret', $argument ); } else { diff --git a/apps/federation/backgroundjob/requestsharedsecret.php b/apps/federation/backgroundjob/requestsharedsecret.php index f5685e2e0c2..24d8adada11 100644 --- a/apps/federation/backgroundjob/requestsharedsecret.php +++ b/apps/federation/backgroundjob/requestsharedsecret.php @@ -106,10 +106,18 @@ class RequestSharedSecret extends QueuedJob { $target = $this->argument['url']; // only execute if target is still in the list of trusted domains if ($this->trustedServers->isTrustedServer($target)) { - parent::execute($jobList, $logger); + $this->parentExecute($jobList, $logger); } } + /** + * @param JobList $jobList + * @param ILogger $logger + */ + protected function parentExecute($jobList, $logger) { + parent::execute($jobList, $logger); + } + protected function run($argument) { $target = $argument['url']; diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index 976a48f8b09..61ba5c87cfd 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -82,7 +82,7 @@ class DbHandler { $result = $query->execute(); if ($result) { - return $this->connection->lastInsertId('*PREFIX*'.$this->dbTable); + return (int)$this->connection->lastInsertId('*PREFIX*'.$this->dbTable); } else { $message = 'Internal failure, Could not add ownCloud as trusted server: ' . $url; $message_t = $this->l->t('Could not add server'); @@ -231,7 +231,7 @@ class DbHandler { ->setParameter('url_hash', $hash); $result = $query->execute()->fetch(); - return $result['status']; + return (int)$result['status']; } /** diff --git a/apps/federation/tests/backgroundjob/getsharedsecrettest.php b/apps/federation/tests/backgroundjob/getsharedsecrettest.php new file mode 100644 index 00000000000..953af5ff3e1 --- /dev/null +++ b/apps/federation/tests/backgroundjob/getsharedsecrettest.php @@ -0,0 +1,190 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\BackgroundJob; + + +use OCA\Federation\BackgroundJob\GetSharedSecret; +use OCA\Files_Sharing\Tests\TestCase; +use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; +use OCP\AppFramework\Http; +use OCP\BackgroundJob\IJobList; +use OCP\Http\Client\IClient; +use OCP\Http\Client\IResponse; +use OCP\ILogger; +use OCP\IURLGenerator; + +class GetSharedSecretTest extends TestCase { + + /** @var \PHPUnit_Framework_MockObject_MockObject | IClient */ + private $httpClient; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IJobList */ + private $jobList; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IURLGenerator */ + private $urlGenerator; + + /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers */ + private $trustedServers; + + /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */ + private $dbHandler; + + /** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */ + private $logger; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */ + private $response; + + /** @var GetSharedSecret */ + private $getSharedSecret; + + public function setUp() { + parent::setUp(); + + $this->httpClient = $this->getMock('OCP\Http\Client\IClient'); + $this->jobList = $this->getMock('OCP\BackgroundJob\IJobList'); + $this->urlGenerator = $this->getMock('OCP\IURLGenerator'); + $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->disableOriginalConstructor()->getMock(); + $this->dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler') + ->disableOriginalConstructor()->getMock(); + $this->logger = $this->getMock('OCP\ILogger'); + $this->response = $this->getMock('OCP\Http\Client\IResponse'); + + $this->getSharedSecret = new GetSharedSecret( + $this->httpClient, + $this->urlGenerator, + $this->jobList, + $this->trustedServers, + $this->logger, + $this->dbHandler + ); + } + + /** + * @dataProvider dataTestExecute + * + * @param bool $isTrustedServer + */ + public function testExecute($isTrustedServer) { + /** @var GetSharedSecret |\PHPUnit_Framework_MockObject_MockObject $getSharedSecret */ + $getSharedSecret = $this->getMockBuilder('OCA\Federation\BackgroundJob\GetSharedSecret') + ->setConstructorArgs( + [ + $this->httpClient, + $this->urlGenerator, + $this->jobList, + $this->trustedServers, + $this->logger, + $this->dbHandler + ] + )->setMethods(['parentExecute'])->getMock(); + $this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url']]); + + $this->jobList->expects($this->once())->method('remove'); + $this->trustedServers->expects($this->once())->method('isTrustedServer') + ->with('url')->willReturn($isTrustedServer); + if ($isTrustedServer) { + $getSharedSecret->expects($this->once())->method('parentExecute'); + } else { + $getSharedSecret->expects($this->never())->method('parentExecute'); + } + + $getSharedSecret->execute($this->jobList); + + } + + public function dataTestExecute() { + return [ + [true], + [false] + ]; + } + + /** + * @dataProvider dataTestRun + * + * @param int $statusCode + */ + public function testRun($statusCode) { + + $target = 'targetURL'; + $source = 'sourceURL'; + $token = 'token'; + + $argument = ['url' => $target, 'token' => $token]; + + $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')->with('/') + ->willReturn($source); + $this->httpClient->expects($this->once())->method('get') + ->with( + $target . '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json', + [ + 'query' => + [ + 'url' => $source, + 'token' => $token + ], + 'timeout' => 3, + 'connect_timeout' => 3, + ] + )->willReturn($this->response); + + $this->response->expects($this->once())->method('getStatusCode') + ->willReturn($statusCode); + + if ( + $statusCode !== Http::STATUS_OK + && $statusCode !== Http::STATUS_FORBIDDEN + ) { + $this->jobList->expects($this->once())->method('add') + ->with('OCA\Federation\BackgroundJob\GetSharedSecret', $argument); + $this->dbHandler->expects($this->never())->method('addToken'); + } else { + $this->dbHandler->expects($this->once())->method('addToken')->with($target, ''); + $this->jobList->expects($this->never())->method('add'); + } + + if ($statusCode === Http::STATUS_OK) { + $this->response->expects($this->once())->method('getBody') + ->willReturn('{"ocs":{"data":{"sharedSecret":"secret"}}}'); + $this->trustedServers->expects($this->once())->method('addSharedSecret') + ->with($target, 'secret'); + } else { + $this->trustedServers->expects($this->never())->method('addSharedSecret'); + } + + $this->invokePrivate($this->getSharedSecret, 'run', [$argument]); + } + + public function dataTestRun() { + return [ + [Http::STATUS_OK], + [Http::STATUS_FORBIDDEN], + [Http::STATUS_CONFLICT], + ]; + } + +} diff --git a/apps/federation/tests/backgroundjob/requestsharedsecrettest.php b/apps/federation/tests/backgroundjob/requestsharedsecrettest.php new file mode 100644 index 00000000000..df81113c686 --- /dev/null +++ b/apps/federation/tests/backgroundjob/requestsharedsecrettest.php @@ -0,0 +1,169 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Federation\Tests\BackgroundJob; + + +use OCA\Federation\BackgroundJob\RequestSharedSecret; +use OCP\AppFramework\Http; +use Test\TestCase; + +class RequestSharedSecretTest extends TestCase { + + /** @var \PHPUnit_Framework_MockObject_MockObject | IClient */ + private $httpClient; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IJobList */ + private $jobList; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IURLGenerator */ + private $urlGenerator; + + /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */ + private $dbHandler; + + /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers */ + private $trustedServers; + + /** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */ + private $response; + + /** @var RequestSharedSecret */ + private $requestSharedSecret; + + public function setUp() { + parent::setUp(); + + $this->httpClient = $this->getMock('OCP\Http\Client\IClient'); + $this->jobList = $this->getMock('OCP\BackgroundJob\IJobList'); + $this->urlGenerator = $this->getMock('OCP\IURLGenerator'); + $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') + ->disableOriginalConstructor()->getMock(); + $this->dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler') + ->disableOriginalConstructor()->getMock(); + $this->response = $this->getMock('OCP\Http\Client\IResponse'); + + $this->requestSharedSecret = new RequestSharedSecret( + $this->httpClient, + $this->urlGenerator, + $this->jobList, + $this->trustedServers, + $this->dbHandler + ); + } + + /** + * @dataProvider dataTestExecute + * + * @param bool $isTrustedServer + */ + public function testExecute($isTrustedServer) { + /** @var RequestSharedSecret |\PHPUnit_Framework_MockObject_MockObject $requestSharedSecret */ + $requestSharedSecret = $this->getMockBuilder('OCA\Federation\BackgroundJob\RequestSharedSecret') + ->setConstructorArgs( + [ + $this->httpClient, + $this->urlGenerator, + $this->jobList, + $this->trustedServers, + $this->dbHandler + ] + )->setMethods(['parentExecute'])->getMock(); + $this->invokePrivate($requestSharedSecret, 'argument', [['url' => 'url']]); + + $this->jobList->expects($this->once())->method('remove'); + $this->trustedServers->expects($this->once())->method('isTrustedServer') + ->with('url')->willReturn($isTrustedServer); + if ($isTrustedServer) { + $requestSharedSecret->expects($this->once())->method('parentExecute'); + } else { + $requestSharedSecret->expects($this->never())->method('parentExecute'); + } + + $requestSharedSecret->execute($this->jobList); + + } + + public function dataTestExecute() { + return [ + [true], + [false] + ]; + } + + /** + * @dataProvider dataTestRun + * + * @param int $statusCode + */ + public function testRun($statusCode) { + + $target = 'targetURL'; + $source = 'sourceURL'; + $token = 'token'; + + $argument = ['url' => $target, 'token' => $token]; + + $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')->with('/') + ->willReturn($source); + $this->httpClient->expects($this->once())->method('post') + ->with( + $target . '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json', + [ + 'body' => + [ + 'url' => $source, + 'token' => $token + ], + 'timeout' => 3, + 'connect_timeout' => 3, + ] + )->willReturn($this->response); + + $this->response->expects($this->once())->method('getStatusCode') + ->willReturn($statusCode); + + if ( + $statusCode !== Http::STATUS_OK + && $statusCode !== Http::STATUS_FORBIDDEN + ) { + $this->jobList->expects($this->once())->method('add') + ->with('OCA\Federation\BackgroundJob\RequestSharedSecret', $argument); + $this->dbHandler->expects($this->never())->method('addToken'); + } + + if ($statusCode === Http::STATUS_FORBIDDEN) { + $this->jobList->expects($this->never())->method('add'); + $this->dbHandler->expects($this->once())->method('addToken')->with($target, ''); + } + + $this->invokePrivate($this->requestSharedSecret, 'run', [$argument]); + } + + public function dataTestRun() { + return [ + [Http::STATUS_OK], + [Http::STATUS_FORBIDDEN], + [Http::STATUS_CONFLICT], + ]; + } +} diff --git a/apps/federation/tests/lib/dbhandlertest.php b/apps/federation/tests/lib/dbhandlertest.php index 50bb9a73d92..e47df092f8c 100644 --- a/apps/federation/tests/lib/dbhandlertest.php +++ b/apps/federation/tests/lib/dbhandlertest.php @@ -24,6 +24,7 @@ namespace OCA\Federation\Tests\lib; use OCA\Federation\DbHandler; +use OCA\Federation\TrustedServers; use OCP\IDBConnection; use Test\TestCase; @@ -73,7 +74,8 @@ class DbHandlerTest extends TestCase { $result = $query->execute()->fetchAll(); $this->assertSame(1, count($result)); $this->assertSame('server1', $result[0]['url']); - $this->assertSame($id, $result[0]['id']); + $this->assertSame($id, (int)$result[0]['id']); + $this->assertSame(TrustedServers::STATUS_PENDING, (int)$result[0]['status']); } public function testRemove() { @@ -85,15 +87,15 @@ class DbHandlerTest extends TestCase { $this->assertSame(2, count($result)); $this->assertSame('server1', $result[0]['url']); $this->assertSame('server2', $result[1]['url']); - $this->assertSame($id1, $result[0]['id']); - $this->assertSame($id2, $result[1]['id']); + $this->assertSame($id1, (int)$result[0]['id']); + $this->assertSame($id2, (int)$result[1]['id']); $this->dbHandler->removeServer($id2); $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); $result = $query->execute()->fetchAll(); $this->assertSame(1, count($result)); $this->assertSame('server1', $result[0]['url']); - $this->assertSame($id1, $result[0]['id']); + $this->assertSame($id1, (int)$result[0]['id']); } public function testGetAll() { @@ -104,32 +106,118 @@ class DbHandlerTest extends TestCase { $this->assertSame(2, count($result)); $this->assertSame('server1', $result[0]['url']); $this->assertSame('server2', $result[1]['url']); - $this->assertSame($id1, $result[0]['id']); - $this->assertSame($id2, $result[1]['id']); + $this->assertSame($id1, (int)$result[0]['id']); + $this->assertSame($id2, (int)$result[1]['id']); } /** - * @dataProvider dataTestExists + * @dataProvider dataTestServerExists * * @param string $serverInTable * @param string $checkForServer * @param bool $expected */ - public function testExists($serverInTable, $checkForServer, $expected) { + public function testServerExists($serverInTable, $checkForServer, $expected) { $this->dbHandler->addServer($serverInTable); $this->assertSame($expected, $this->dbHandler->serverExists($checkForServer) ); } - public function dataTestExists() { + public function dataTestServerExists() { return [ ['server1', 'server1', true], - ['server1', 'server1', true], + ['server1', 'http://server1', true], ['server1', 'server2', false] ]; } + public function testAddToken() { + $this->dbHandler->addServer('server1'); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame(null, $result[0]['token']); + $this->dbHandler->addToken('http://server1', 'token'); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame('token', $result[0]['token']); + } + + public function testGetToken() { + $this->dbHandler->addServer('server1'); + $this->dbHandler->addToken('http://server1', 'token'); + $this->assertSame('token', + $this->dbHandler->getToken('https://server1') + ); + } + + public function testAddSharedSecret() { + $this->dbHandler->addServer('server1'); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame(null, $result[0]['shared_secret']); + $this->dbHandler->addSharedSecret('http://server1', 'secret'); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame('secret', $result[0]['shared_secret']); + } + + public function testGetSharedSecret() { + $this->dbHandler->addServer('server1'); + $this->dbHandler->addSharedSecret('http://server1', 'secret'); + $this->assertSame('secret', + $this->dbHandler->getSharedSecret('https://server1') + ); + } + + public function testSetServerStatus() { + $this->dbHandler->addServer('server1'); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame(TrustedServers::STATUS_PENDING, (int)$result[0]['status']); + $this->dbHandler->setServerStatus('http://server1', TrustedServers::STATUS_OK); + $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); + $result = $query->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame(TrustedServers::STATUS_OK, (int)$result[0]['status']); + } + + public function testGetServerStatus() { + $this->dbHandler->addServer('server1'); + $this->dbHandler->setServerStatus('http://server1', TrustedServers::STATUS_OK); + $this->assertSame(TrustedServers::STATUS_OK, + $this->dbHandler->getServerStatus('https://server1') + ); + } + + /** + * hash should always be computed with the normalized URL + * + * @dataProvider dataTestHash + * + * @param string $url + * @param string $expected + */ + public function testHash($url, $expected) { + $this->assertSame($expected, + $this->invokePrivate($this->dbHandler, 'hash', [$url]) + ); + } + + public function dataTestHash() { + return [ + ['server1', md5('server1')], + ['http://server1', md5('server1')], + ['https://server1', md5('server1')], + ['http://server1/', md5('server1')], + ]; + } + /** * @dataProvider dataTestNormalizeUrl * diff --git a/apps/federation/tests/lib/trustedserverstest.php b/apps/federation/tests/lib/trustedserverstest.php index dabf353ef21..d067cd1c185 100644 --- a/apps/federation/tests/lib/trustedserverstest.php +++ b/apps/federation/tests/lib/trustedserverstest.php @@ -88,7 +88,7 @@ class TrustedServersTest extends TestCase { } /** - * @dataProvider dataTestAddServer + * @dataProvider dataTrueFalse * * @param bool $success */ @@ -130,13 +130,66 @@ class TrustedServersTest extends TestCase { ); } - public function dataTestAddServer() { + public function dataTrueFalse() { return [ [true], [false] ]; } + /** + * @dataProvider dataTrueFalse + * + * @param bool $status + */ + public function testSetAutoAddServers($status) { + if ($status) { + $this->config->expects($this->once())->method('setAppValue') + ->with('federation', 'autoAddServers', '1'); + } else { + $this->config->expects($this->once())->method('setAppValue') + ->with('federation', 'autoAddServers', '0'); + } + + $this->trustedServers->setAutoAddServers($status); + } + + /** + * @dataProvider dataTestGetAutoAddServers + * + * @param string $status + * @param bool $expected + */ + public function testGetAutoAddServers($status, $expected) { + $this->config->expects($this->once())->method('getAppValue') + ->with('federation', 'autoAddServers', '1')->willReturn($status); + + $this->assertSame($expected, + $this->trustedServers->getAutoAddServers($status) + ); + } + + public function dataTestGetAutoAddServers() { + return [ + ['1', true], + ['0', false] + ]; + } + + public function testAddSharedSecret() { + $this->dbHandler->expects($this->once())->method('addSharedSecret') + ->with('url', 'secret'); + $this->trustedServers->addSharedSecret('url', 'secret'); + } + + public function testGetSharedSecret() { + $this->dbHandler->expects($this->once())->method('getSharedSecret') + ->with('url')->willReturn(true); + $this->assertTrue( + $this->trustedServers->getSharedSecret('url') + ); + } + public function testRemoveServer() { $id = 42; $this->dbHandler->expects($this->once())->method('removeServer')->with($id); @@ -161,6 +214,20 @@ class TrustedServersTest extends TestCase { ); } + public function testSetServerStatus() { + $this->dbHandler->expects($this->once())->method('setServerStatus') + ->with('url', 'status'); + $this->trustedServers->setServerStatus('url', 'status'); + } + + public function testGetServerStatus() { + $this->dbHandler->expects($this->once())->method('getServerStatus') + ->with('url')->willReturn(true); + $this->assertTrue( + $this->trustedServers->getServerStatus('url') + ); + } + /** * @dataProvider dataTestIsOwnCloudServer * -- GitLab From 0265bcfdae6eff2ea87eb0f6de66e2eacb590820 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Sun, 8 Nov 2015 22:08:19 +0100 Subject: [PATCH 110/344] Moved changedisplayname to usercontroller Killed the old static route to change a users display name and moved it to a properly testable controller. --- settings/ajax/changedisplayname.php | 67 ------- settings/controller/userscontroller.php | 54 ++++++ settings/js/personal.js | 2 +- settings/js/users/users.js | 2 +- settings/routes.php | 3 +- .../controller/userscontrollertest.php | 169 ++++++++++++++++++ 6 files changed, 226 insertions(+), 71 deletions(-) delete mode 100644 settings/ajax/changedisplayname.php diff --git a/settings/ajax/changedisplayname.php b/settings/ajax/changedisplayname.php deleted file mode 100644 index 380cbac43da..00000000000 --- a/settings/ajax/changedisplayname.php +++ /dev/null @@ -1,67 +0,0 @@ - - * @author Christopher Schäpers - * @author David Reagan - * @author Jan-Christoph Borchardt - * @author Lukas Reschke - * @author Robin Appelman - * - * @copyright Copyright (c) 2015, 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 - * - */ -// Check if we are a user - -OCP\JSON::callCheck(); -OC_JSON::checkLoggedIn(); - -$l = \OC::$server->getL10N('settings'); - -$username = isset($_POST["username"]) ? $_POST["username"] : OC_User::getUser(); -$displayName = (string)$_POST["displayName"]; - -$userstatus = null; -if(OC_User::isAdminUser(OC_User::getUser())) { - $userstatus = 'admin'; -} - -$isUserAccessible = false; -$subadminUserObject = \OC::$server->getUserManager()->get(\OC_User::getUser()); -$targetUserObject = \OC::$server->getUserManager()->get($username); -if($subadminUserObject !== null && $targetUserObject !== null) { - $isUserAccessible = \OC::$server->getGroupManager()->getSubAdmin()->isUserAccessible($subadminUserObject, $targetUserObject); -} - -if($isUserAccessible) { - $userstatus = 'subadmin'; -} - -if ($username === OC_User::getUser() && OC_User::canUserChangeDisplayName($username)) { - $userstatus = 'changeOwnDisplayName'; -} - -if(is_null($userstatus)) { - OC_JSON::error( array( "data" => array( "message" => $l->t("Authentication error") ))); - exit(); -} - -// Return Success story -if( OC_User::setDisplayName( $username, $displayName )) { - OC_JSON::success(array("data" => array( "message" => $l->t('Your full name has been changed.'), "username" => $username, 'displayName' => $displayName ))); -} -else{ - OC_JSON::error(array("data" => array( "message" => $l->t("Unable to change full name"), 'displayName' => OC_User::getDisplayName($username) ))); -} diff --git a/settings/controller/userscontroller.php b/settings/controller/userscontroller.php index 82483a76245..942319901f3 100644 --- a/settings/controller/userscontroller.php +++ b/settings/controller/userscontroller.php @@ -585,4 +585,58 @@ class UsersController extends Controller { ); } + + /** + * Set the displayName of a user + * + * @NoAdminRequired + * @NoSubadminRequired + * + * @param string $username + * @param string $displayName + * @return DataResponse + */ + public function setDisplayName($username, $displayName) { + $currentUser = $this->userSession->getUser(); + + if ($username === null) { + $username = $currentUser->getUID(); + } + + $user = $this->userManager->get($username); + + if ($user === null || + !$user->canChangeDisplayName() || + ( + !$this->groupManager->isAdmin($currentUser->getUID()) && + !$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user) && + $currentUser !== $user) + ) { + return new DataResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l10n->t('Authentication error'), + ], + ]); + } + + if ($user->setDisplayName($displayName)) { + return new DataResponse([ + 'status' => 'success', + 'data' => [ + 'message' => $this->l10n->t('Your full name has been changed.'), + 'username' => $username, + 'displayName' => $displayName, + ], + ]); + } else { + return new DataResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l10n->t('Unable to change full name'), + 'displayName' => $user->getDisplayName(), + ], + ]); + } + } } diff --git a/settings/js/personal.js b/settings/js/personal.js index 3439eba686f..c9280d31353 100644 --- a/settings/js/personal.js +++ b/settings/js/personal.js @@ -70,7 +70,7 @@ function changeDisplayName () { // Serialize the data var post = $("#displaynameform").serialize(); // Ajax foo - $.post('ajax/changedisplayname.php', post, function (data) { + $.post(OC.generateUrl('/settings/users/{id}/displayName', {id: OC.currentUser}), post, function (data) { if (data.status === "success") { $('#oldDisplayName').val($('#displayName').val()); // update displayName on the top right expand button diff --git a/settings/js/users/users.js b/settings/js/users/users.js index 8ce9cb6ac7c..c20a21b060a 100644 --- a/settings/js/users/users.js +++ b/settings/js/users/users.js @@ -687,7 +687,7 @@ $(document).ready(function () { $div.imageplaceholder(uid, displayName); } $.post( - OC.filePath('settings', 'ajax', 'changedisplayname.php'), + OC.generateUrl('/settings/users/{id}/displayName', {id: uid}), {username: uid, displayName: $(this).val()}, function (result) { if (result && result.status==='success' && $div.length){ diff --git a/settings/routes.php b/settings/routes.php index 6ba38388d3a..95ad234c699 100644 --- a/settings/routes.php +++ b/settings/routes.php @@ -46,6 +46,7 @@ $application->registerRoutes($this, [ ['name' => 'AppSettings#listApps', 'url' => '/settings/apps/list', 'verb' => 'GET'], ['name' => 'AppSettings#changeExperimentalConfigState', 'url' => '/settings/apps/experimental', 'verb' => 'POST'], ['name' => 'SecuritySettings#trustedDomains', 'url' => '/settings/admin/security/trustedDomains', 'verb' => 'POST'], + ['name' => 'Users#setDisplayName', 'url' => '/settings/users/{username}/displayName', 'verb' => 'POST'], ['name' => 'Users#setMailAddress', 'url' => '/settings/users/{id}/mailAddress', 'verb' => 'PUT'], ['name' => 'Users#stats', 'url' => '/settings/users/stats', 'verb' => 'GET'], ['name' => 'LogSettings#setLogLevel', 'url' => '/settings/admin/log/level', 'verb' => 'POST'], @@ -79,8 +80,6 @@ $this->create('settings_ajax_togglesubadmins', '/settings/ajax/togglesubadmins.p $this->create('settings_users_changepassword', '/settings/users/changepassword') ->post() ->action('OC\Settings\ChangePassword\Controller', 'changeUserPassword'); -$this->create('settings_ajax_changedisplayname', '/settings/ajax/changedisplayname.php') - ->actionInclude('settings/ajax/changedisplayname.php'); $this->create('settings_ajax_changegorupname', '/settings/ajax/changegroupname.php') ->actionInclude('settings/ajax/changegroupname.php'); // personal diff --git a/tests/settings/controller/userscontrollertest.php b/tests/settings/controller/userscontrollertest.php index f4b05671ce8..b10737035ea 100644 --- a/tests/settings/controller/userscontrollertest.php +++ b/tests/settings/controller/userscontrollertest.php @@ -1746,4 +1746,173 @@ class UsersControllerTest extends \Test\TestCase { $this->assertEquals($expectedResponse, $response); } + public function testSetDisplayNameNull() { + $user = $this->getMock('\OCP\IUser'); + $user->method('getUID')->willReturn('userName'); + + $this->container['UserSession'] + ->expects($this->once()) + ->method('getUser') + ->willReturn($user); + + $expectedResponse = new DataResponse( + [ + 'status' => 'error', + 'data' => [ + 'message' => 'Authentication error', + ], + ] + ); + $response = $this->container['UsersController']->setDisplayName(null, 'displayName'); + + $this->assertEquals($expectedResponse, $response); + } + + public function dataSetDisplayName() { + $data = []; + + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + $user1->method('canChangeDisplayName')->willReturn(true); + $data[] = [$user1, $user1, false, false, true]; + + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + $user1->method('canChangeDisplayName')->willReturn(false); + $data[] = [$user1, $user1, false, false, false]; + + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + $user2 = $this->getMock('\OCP\IUser'); + $user2->method('getUID')->willReturn('user2'); + $user2->method('canChangeDisplayName')->willReturn(true); + $data[] = [$user1, $user2, false, false, false]; + + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + $user2 = $this->getMock('\OCP\IUser'); + $user2->method('getUID')->willReturn('user2'); + $user2->method('canChangeDisplayName')->willReturn(true); + $data[] = [$user1, $user2, true, false, true]; + + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + $user2 = $this->getMock('\OCP\IUser'); + $user2->method('getUID')->willReturn('user2'); + $user2->method('canChangeDisplayName')->willReturn(true); + $data[] = [$user1, $user2, false, true, true]; + + return $data; + } + + /** + * @dataProvider dataSetDisplayName + */ + public function testSetDisplayName($currentUser, $editUser, $isAdmin, $isSubAdmin, $valid) { + $this->container['UserSession'] + ->expects($this->once()) + ->method('getUser') + ->willReturn($currentUser); + $this->container['UserManager'] + ->expects($this->once()) + ->method('get') + ->with($editUser->getUID()) + ->willReturn($editUser); + + $subadmin = $this->getMockBuilder('\OC\SubAdmin') + ->disableOriginalConstructor() + ->getMock(); + $subadmin + ->method('isUserAccessible') + ->with($currentUser, $editUser) + ->willReturn($isSubAdmin); + + $this->container['GroupManager'] + ->method('getSubAdmin') + ->willReturn($subadmin); + $this->container['GroupManager'] + ->method('isAdmin') + ->with($currentUser->getUID()) + ->willReturn($isAdmin); + + if ($valid === true) { + $editUser->expects($this->once()) + ->method('setDisplayName') + ->with('newDisplayName') + ->willReturn(true); + $expectedResponse = new DataResponse( + [ + 'status' => 'success', + 'data' => [ + 'message' => 'Your full name has been changed.', + 'username' => $editUser->getUID(), + 'displayName' => 'newDisplayName', + ], + ] + ); + } else { + $editUser->expects($this->never())->method('setDisplayName'); + $expectedResponse = new DataResponse( + [ + 'status' => 'error', + 'data' => [ + 'message' => 'Authentication error', + ], + ] + ); + } + + $response = $this->container['UsersController']->setDisplayName($editUser->getUID(), 'newDisplayName'); + $this->assertEquals($expectedResponse, $response); + } + + public function testSetDisplayNameFails() { + $user = $this->getMock('\OCP\IUser'); + $user->method('canChangeDisplayname')->willReturn(true); + $user->method('getUID')->willReturn('user'); + $user->expects($this->once()) + ->method('setDisplayName') + ->with('newDisplayName') + ->willReturn(false); + $user->method('getDisplayName')->willReturn('oldDisplayName'); + + $this->container['UserSession'] + ->expects($this->once()) + ->method('getUser') + ->willReturn($user); + $this->container['UserManager'] + ->expects($this->once()) + ->method('get') + ->with($user->getUID()) + ->willReturn($user); + + $subadmin = $this->getMockBuilder('\OC\SubAdmin') + ->disableOriginalConstructor() + ->getMock(); + $subadmin + ->method('isUserAccessible') + ->with($user, $user) + ->willReturn(false); + + $this->container['GroupManager'] + ->method('getSubAdmin') + ->willReturn($subadmin); + $this->container['GroupManager'] + ->expects($this->once()) + ->method('isAdmin') + ->with($user->getUID()) + ->willReturn(false); + + $expectedResponse = new DataResponse( + [ + 'status' => 'error', + 'data' => [ + 'message' => 'Unable to change full name', + 'displayName' => 'oldDisplayName', + ], + ] + ); + $response = $this->container['UsersController']->setDisplayName($user->getUID(), 'newDisplayName'); + $this->assertEquals($expectedResponse, $response); + } } -- GitLab From 5573029485f7ecea806d3c58f6f0204c2e0651ad Mon Sep 17 00:00:00 2001 From: Scrutinizer Auto-Fixer Date: Fri, 20 Nov 2015 15:42:34 +0000 Subject: [PATCH 111/344] Scrutinizer Auto-Fixes This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com --- apps/dav/lib/caldav/caldavbackend.php | 7 +++---- apps/dav/lib/carddav/carddavbackend.php | 6 +++--- apps/dav/lib/connector/sabre/auth.php | 2 +- apps/dav/lib/connector/sabre/fakelockerplugin.php | 4 ++-- apps/dav/lib/connector/sabre/file.php | 10 ++++++++-- apps/dav/lib/connector/sabre/lockplugin.php | 1 - apps/dav/lib/connector/sabre/node.php | 6 +++--- apps/dav/lib/connector/sabre/principal.php | 2 +- apps/dav/tests/unit/connector/sabre/file.php | 5 ++++- apps/dav/tests/unit/connector/sabre/filesplugin.php | 3 +++ .../tests/unit/connector/sabre/requesttest/auth.php | 4 ++-- 11 files changed, 30 insertions(+), 20 deletions(-) diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php index 08a2a70c56d..99338650793 100644 --- a/apps/dav/lib/caldav/caldavbackend.php +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -217,7 +217,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * * Read the PropPatch documentation for more info and examples. * - * @param string $path * @param \Sabre\DAV\PropPatch $propPatch * @return void */ @@ -375,7 +374,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * If the backend supports this, it may allow for some speed-ups. * * @param mixed $calendarId - * @param array $uris + * @param string[] $uris * @return array */ function getMultipleCalendarObjects($calendarId, array $uris) { @@ -422,7 +421,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @param mixed $calendarId * @param string $objectUri * @param string $calendarData - * @return string|null + * @return string */ function createCalendarObject($calendarId, $objectUri, $calendarData) { $extraData = $this->getDenormalizedData($calendarData); @@ -464,7 +463,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @param mixed $calendarId * @param string $objectUri * @param string $calendarData - * @return string|null + * @return string */ function updateCalendarObject($calendarId, $objectUri, $calendarData) { $extraData = $this->getDenormalizedData($calendarData); diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index 348c166a531..daa31725fa1 100644 --- a/apps/dav/lib/carddav/carddavbackend.php +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -343,7 +343,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { * If the backend supports this, it may allow for some speed-ups. * * @param mixed $addressBookId - * @param array $uris + * @param string[] $uris * @return array */ function getMultipleCards($addressBookId, array $uris) { @@ -390,7 +390,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { * @param mixed $addressBookId * @param string $cardUri * @param string $cardData - * @return string|null + * @return string */ function createCard($addressBookId, $cardUri, $cardData) { $etag = md5($cardData); @@ -435,7 +435,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { * @param mixed $addressBookId * @param string $cardUri * @param string $cardData - * @return string|null + * @return string */ function updateCard($addressBookId, $cardUri, $cardData) { diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php index 0394bfd6772..f9a39799046 100644 --- a/apps/dav/lib/connector/sabre/auth.php +++ b/apps/dav/lib/connector/sabre/auth.php @@ -150,7 +150,7 @@ class Auth extends AbstractBasic { /** * @param \Sabre\DAV\Server $server - * @param $realm + * @param string $realm * @return bool */ private function auth(\Sabre\DAV\Server $server, $realm) { diff --git a/apps/dav/lib/connector/sabre/fakelockerplugin.php b/apps/dav/lib/connector/sabre/fakelockerplugin.php index 493d3b0ade4..b9d1a30a041 100644 --- a/apps/dav/lib/connector/sabre/fakelockerplugin.php +++ b/apps/dav/lib/connector/sabre/fakelockerplugin.php @@ -59,7 +59,7 @@ class FakeLockerPlugin extends ServerPlugin { * Indicate that we support LOCK and UNLOCK * * @param string $path - * @return array + * @return string[] */ public function getHTTPMethods($path) { return [ @@ -71,7 +71,7 @@ class FakeLockerPlugin extends ServerPlugin { /** * Indicate that we support locking * - * @return array + * @return integer[] */ function getFeatures() { return [2]; diff --git a/apps/dav/lib/connector/sabre/file.php b/apps/dav/lib/connector/sabre/file.php index a0c35fb2baf..ef7b9891dc9 100644 --- a/apps/dav/lib/connector/sabre/file.php +++ b/apps/dav/lib/connector/sabre/file.php @@ -213,6 +213,9 @@ class File extends Node implements IFile { return '"' . $this->info->getEtag() . '"'; } + /** + * @param string $path + */ private function emitPreHooks($exists, $path = null) { if (is_null($path)) { $path = $this->path; @@ -238,6 +241,9 @@ class File extends Node implements IFile { return $run; } + /** + * @param string $path + */ private function emitPostHooks($exists, $path = null) { if (is_null($path)) { $path = $this->path; @@ -260,7 +266,7 @@ class File extends Node implements IFile { /** * Returns the data * - * @return string|resource + * @return resource * @throws Forbidden * @throws ServiceUnavailable */ @@ -314,7 +320,7 @@ class File extends Node implements IFile { * * If null is returned, we'll assume application/octet-stream * - * @return mixed + * @return string */ public function getContentType() { $mimeType = $this->info->getMimetype(); diff --git a/apps/dav/lib/connector/sabre/lockplugin.php b/apps/dav/lib/connector/sabre/lockplugin.php index 8032d2b3fbf..d770b141eb9 100644 --- a/apps/dav/lib/connector/sabre/lockplugin.php +++ b/apps/dav/lib/connector/sabre/lockplugin.php @@ -27,7 +27,6 @@ use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\ServerPlugin; -use Sabre\DAV\Tree; use Sabre\HTTP\RequestInterface; class LockPlugin extends ServerPlugin { diff --git a/apps/dav/lib/connector/sabre/node.php b/apps/dav/lib/connector/sabre/node.php index daf82ba6f0d..c4e0614077f 100644 --- a/apps/dav/lib/connector/sabre/node.php +++ b/apps/dav/lib/connector/sabre/node.php @@ -178,7 +178,7 @@ abstract class Node implements \Sabre\DAV\INode { /** * Returns the size of the node, in bytes * - * @return int|float + * @return integer */ public function getSize() { return $this->info->getSize(); @@ -207,14 +207,14 @@ abstract class Node implements \Sabre\DAV\INode { } /** - * @return string + * @return integer */ public function getInternalFileId() { return $this->info->getId(); } /** - * @return string|null + * @return string */ public function getDavPermissions() { $p = ''; diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php index 35215e1f63c..7fb14c031f9 100644 --- a/apps/dav/lib/connector/sabre/principal.php +++ b/apps/dav/lib/connector/sabre/principal.php @@ -168,7 +168,7 @@ class Principal implements \Sabre\DAVACL\PrincipalBackend\BackendInterface { * The principals should be passed as a list of uri's. * * @param string $principal - * @param array $members + * @param string[] $members * @throws \Sabre\DAV\Exception */ public function setGroupMemberSet($principal, array $members) { diff --git a/apps/dav/tests/unit/connector/sabre/file.php b/apps/dav/tests/unit/connector/sabre/file.php index 399634f8bee..0a52299cec7 100644 --- a/apps/dav/tests/unit/connector/sabre/file.php +++ b/apps/dav/tests/unit/connector/sabre/file.php @@ -41,6 +41,9 @@ class File extends \Test\TestCase { parent::tearDown(); } + /** + * @param string $string + */ private function getStream($string) { $stream = fopen('php://temp', 'r+'); fwrite($stream, $string); @@ -239,7 +242,7 @@ class File extends \Test\TestCase { * @param string $path path to put the file into * @param string $viewRoot root to use for the view * - * @return result of the PUT operaiton which is usually the etag + * @return null|string of the PUT operaiton which is usually the etag */ private function doPut($path, $viewRoot = null) { $view = \OC\Files\Filesystem::getView(); diff --git a/apps/dav/tests/unit/connector/sabre/filesplugin.php b/apps/dav/tests/unit/connector/sabre/filesplugin.php index 2e3338fefa1..b33c8340f72 100644 --- a/apps/dav/tests/unit/connector/sabre/filesplugin.php +++ b/apps/dav/tests/unit/connector/sabre/filesplugin.php @@ -55,6 +55,9 @@ class FilesPlugin extends \Test\TestCase { $this->plugin->initialize($this->server); } + /** + * @param string $class + */ private function createTestNode($class) { $node = $this->getMockBuilder($class) ->disableOriginalConstructor() diff --git a/apps/dav/tests/unit/connector/sabre/requesttest/auth.php b/apps/dav/tests/unit/connector/sabre/requesttest/auth.php index 41b554d11db..02b64ab070b 100644 --- a/apps/dav/tests/unit/connector/sabre/requesttest/auth.php +++ b/apps/dav/tests/unit/connector/sabre/requesttest/auth.php @@ -41,7 +41,7 @@ class Auth implements BackendInterface { * * @param \Sabre\DAV\Server $server * @param string $realm - * @return bool + * @return boolean|null */ function authenticate(\Sabre\DAV\Server $server, $realm) { $userSession = \OC::$server->getUserSession(); @@ -61,7 +61,7 @@ class Auth implements BackendInterface { * * If nobody is currently logged in, this method should return null. * - * @return string|null + * @return string */ function getCurrentUser() { return $this->user; -- GitLab From 6bd343a3b755dd4065c61e1623c2d3aa1437c745 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 19 Nov 2015 20:50:26 +0100 Subject: [PATCH 112/344] DB scheme for Comments table, resolves #20265 --- db_structure.xml | 151 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/db_structure.xml b/db_structure.xml index 8135746233e..d4e566d1d54 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -1204,5 +1204,156 @@ + + + *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 + + + + + +
      + -- GitLab From eb42340fa33467f3cd6645136a2ca047b14aab1f Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Sat, 21 Nov 2015 01:54:59 -0500 Subject: [PATCH 113/344] [tx-robot] updated from transifex --- apps/files/l10n/hy.js | 14 +++++++++++++- apps/files/l10n/hy.json | 14 +++++++++++++- apps/files_external/l10n/hy.js | 3 +++ apps/files_external/l10n/hy.json | 3 +++ apps/files_trashbin/l10n/hy.js | 4 +++- apps/files_trashbin/l10n/hy.json | 4 +++- apps/files_versions/l10n/hy.js | 3 ++- apps/files_versions/l10n/hy.json | 3 ++- core/l10n/hy.js | 4 +++- core/l10n/hy.json | 4 +++- settings/l10n/fi_FI.js | 3 +++ settings/l10n/fi_FI.json | 3 +++ settings/l10n/hy.js | 1 + settings/l10n/hy.json | 1 + settings/l10n/it.js | 1 + settings/l10n/it.json | 1 + settings/l10n/ja.js | 1 + settings/l10n/ja.json | 1 + settings/l10n/sq.js | 1 + settings/l10n/sq.json | 1 + 20 files changed, 62 insertions(+), 8 deletions(-) diff --git a/apps/files/l10n/hy.js b/apps/files/l10n/hy.js index 62bc84d6c7b..ae06fed4cd6 100644 --- a/apps/files/l10n/hy.js +++ b/apps/files/l10n/hy.js @@ -2,17 +2,29 @@ OC.L10N.register( "files", { "Files" : "Ֆայլեր", + "All files" : "Բոլոր ֆայլերը", "Close" : "Փակել", "Download" : "Բեռնել", "Rename" : "Վերանվանել", "Delete" : "Ջնջել", "Select" : "Նշել", + "Error" : "Սխալ", + "Could not rename file" : "Չկարողացա վերանվանել ֆայլը", + "Could not create file" : "Չկարողացա ստեղծել ֆայլը", + "Could not create folder" : "Չկարողացա ստեղծել պանակը", "Name" : "Անուն", "Size" : "Չափս", + "Modified" : "Փոփոխված", + "_%n folder_::_%n folders_" : ["%n պանակ","%n պանակ"], + "_%n file_::_%n files_" : ["%n ֆայլ","%n ֆայլ"], + "{dirs} and {files}" : "{dirs} և {files}", "New" : "Նոր", + "_%n byte_::_%n bytes_" : ["%n բայտ","%n բայտ"], "Folder" : "Պանակ", "New folder" : "Նոր պանակ", "Save" : "Պահպանել", - "Select all" : "Նշել բոլորը" + "Select all" : "Նշել բոլորը", + "Text file" : "Տեքստ ֆայլ", + "New text file.txt" : "Նոր տեքստ ֆայլ.txt" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files/l10n/hy.json b/apps/files/l10n/hy.json index c5afd306272..4874c47b3a4 100644 --- a/apps/files/l10n/hy.json +++ b/apps/files/l10n/hy.json @@ -1,16 +1,28 @@ { "translations": { "Files" : "Ֆայլեր", + "All files" : "Բոլոր ֆայլերը", "Close" : "Փակել", "Download" : "Բեռնել", "Rename" : "Վերանվանել", "Delete" : "Ջնջել", "Select" : "Նշել", + "Error" : "Սխալ", + "Could not rename file" : "Չկարողացա վերանվանել ֆայլը", + "Could not create file" : "Չկարողացա ստեղծել ֆայլը", + "Could not create folder" : "Չկարողացա ստեղծել պանակը", "Name" : "Անուն", "Size" : "Չափս", + "Modified" : "Փոփոխված", + "_%n folder_::_%n folders_" : ["%n պանակ","%n պանակ"], + "_%n file_::_%n files_" : ["%n ֆայլ","%n ֆայլ"], + "{dirs} and {files}" : "{dirs} և {files}", "New" : "Նոր", + "_%n byte_::_%n bytes_" : ["%n բայտ","%n բայտ"], "Folder" : "Պանակ", "New folder" : "Նոր պանակ", "Save" : "Պահպանել", - "Select all" : "Նշել բոլորը" + "Select all" : "Նշել բոլորը", + "Text file" : "Տեքստ ֆայլ", + "New text file.txt" : "Նոր տեքստ ֆայլ.txt" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/files_external/l10n/hy.js b/apps/files_external/l10n/hy.js index 9996681f88b..1092d48d575 100644 --- a/apps/files_external/l10n/hy.js +++ b/apps/files_external/l10n/hy.js @@ -2,11 +2,14 @@ OC.L10N.register( "files_external", { "Personal" : "Անձնական", + "Never" : "Երբեք", + "Username" : "Օգտանուն", "Password" : "Գաղտնաբառ", "URL" : "URL", "Dropbox" : "Dropbox", "Share" : "Կիսվել", "Name" : "Անուն", + "Folder name" : "Պանակի անուն", "Delete" : "Ջնջել" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/hy.json b/apps/files_external/l10n/hy.json index ac5a0edf013..1fecd4f3da1 100644 --- a/apps/files_external/l10n/hy.json +++ b/apps/files_external/l10n/hy.json @@ -1,10 +1,13 @@ { "translations": { "Personal" : "Անձնական", + "Never" : "Երբեք", + "Username" : "Օգտանուն", "Password" : "Գաղտնաբառ", "URL" : "URL", "Dropbox" : "Dropbox", "Share" : "Կիսվել", "Name" : "Անուն", + "Folder name" : "Պանակի անուն", "Delete" : "Ջնջել" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/files_trashbin/l10n/hy.js b/apps/files_trashbin/l10n/hy.js index 3cc05b39236..39e49b47ae1 100644 --- a/apps/files_trashbin/l10n/hy.js +++ b/apps/files_trashbin/l10n/hy.js @@ -5,8 +5,10 @@ OC.L10N.register( "Restore" : "Վերականգնել", "Delete" : "Ջնջել", "Delete permanently" : "Ջնջել ընդմիշտ", + "Error" : "Սխալ", "No deleted files" : "Ջնջված ֆայլեր չկան", "Select all" : "Նշել բոլորը", - "Name" : "Անուն" + "Name" : "Անուն", + "Deleted" : "Ջնջված" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_trashbin/l10n/hy.json b/apps/files_trashbin/l10n/hy.json index 994d6afaa58..4bd34056b3f 100644 --- a/apps/files_trashbin/l10n/hy.json +++ b/apps/files_trashbin/l10n/hy.json @@ -3,8 +3,10 @@ "Restore" : "Վերականգնել", "Delete" : "Ջնջել", "Delete permanently" : "Ջնջել ընդմիշտ", + "Error" : "Սխալ", "No deleted files" : "Ջնջված ֆայլեր չկան", "Select all" : "Նշել բոլորը", - "Name" : "Անուն" + "Name" : "Անուն", + "Deleted" : "Ջնջված" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/files_versions/l10n/hy.js b/apps/files_versions/l10n/hy.js index 3924810e149..d48487a9a84 100644 --- a/apps/files_versions/l10n/hy.js +++ b/apps/files_versions/l10n/hy.js @@ -2,6 +2,7 @@ OC.L10N.register( "files_versions", { "Versions" : "Տարբերակներ", - "Restore" : "Վերականգնել" + "Restore" : "Վերականգնել", + "No other versions available" : "Այլ տարբերակներ չկան" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_versions/l10n/hy.json b/apps/files_versions/l10n/hy.json index 7f61c267c7c..579b9240310 100644 --- a/apps/files_versions/l10n/hy.json +++ b/apps/files_versions/l10n/hy.json @@ -1,5 +1,6 @@ { "translations": { "Versions" : "Տարբերակներ", - "Restore" : "Վերականգնել" + "Restore" : "Վերականգնել", + "No other versions available" : "Այլ տարբերակներ չկան" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/core/l10n/hy.js b/core/l10n/hy.js index 841c9a0d4e7..a09ee8f0110 100644 --- a/core/l10n/hy.js +++ b/core/l10n/hy.js @@ -46,6 +46,7 @@ OC.L10N.register( "Very weak password" : "Շատ թույլ գաղտնաբառ", "Weak password" : "Թույլ գաղտնաբառ", "Good password" : "Լավ գաղտնաբառ", + "Error" : "Սխալ", "Share link" : "Կիսվել հղմամբ", "Link" : "Հղում", "Password" : "Գաղտնաբառ", @@ -57,6 +58,7 @@ OC.L10N.register( "Delete" : "Ջնջել", "Add" : "Ավելացնել", "New password" : "Նոր գաղտնաբառ", - "Personal" : "Անձնական" + "Personal" : "Անձնական", + "Username" : "Օգտանուն" }, "nplurals=2; plural=(n != 1);"); diff --git a/core/l10n/hy.json b/core/l10n/hy.json index 722975e72e3..52bc1322a8e 100644 --- a/core/l10n/hy.json +++ b/core/l10n/hy.json @@ -44,6 +44,7 @@ "Very weak password" : "Շատ թույլ գաղտնաբառ", "Weak password" : "Թույլ գաղտնաբառ", "Good password" : "Լավ գաղտնաբառ", + "Error" : "Սխալ", "Share link" : "Կիսվել հղմամբ", "Link" : "Հղում", "Password" : "Գաղտնաբառ", @@ -55,6 +56,7 @@ "Delete" : "Ջնջել", "Add" : "Ավելացնել", "New password" : "Նոր գաղտնաբառ", - "Personal" : "Անձնական" + "Personal" : "Անձնական", + "Username" : "Օգտանուն" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/settings/l10n/fi_FI.js b/settings/l10n/fi_FI.js index de232eee730..9d0ca9371b5 100644 --- a/settings/l10n/fi_FI.js +++ b/settings/l10n/fi_FI.js @@ -154,7 +154,9 @@ OC.L10N.register( "Use system's cron service to call the cron.php file every 15 minutes." : "Käytä järjestelmän cron-palvelua cron.php-tiedoston kutsumista varten 15 minuutin välein.", "Enable server-side encryption" : "Käytä palvelinpään salausta", "Please read carefully before activating server-side encryption: " : "Lue tarkasti, ennen kuin otat palvelinpään salauksen käyttöön:", + "Encryption alone does not guarantee security of the system. Please see ownCloud documentation for more information about how the encryption app works, and the supported use cases." : "Salaaminen pelkästään ei takaa järjestelmän tietoturvaa. Tutustu ownCloudin dokumentaation saadaksesi lisätietoja salaussovelluksen toiminnasta ja tuetuista käyttötapauksista.", "Be aware that encryption always increases the file size." : "Ota huomioon, että salaus kasvattaa aina tiedostojen kokoa.", + "It is always good to create regular backups of your data, in case of encryption make sure to backup the encryption keys along with your data." : "Säännöllisten varmuuskopioiden ottaminen on erittäin tärkeää. Jos olet ottanut salauksen käyttöön, huolehdi salausavainten varmuuskopioinnista.", "This is the final warning: Do you really want to enable encryption?" : "Tämä on viimeinen varoitus: haluatko varmasti ottaa salauksen käyttöön?", "Enable encryption" : "Käytä salausta", "No encryption module loaded, please enable an encryption module in the app menu." : "Salausmoduulia ei ole käytössä. Ota salausmoduuli käyttöön sovellusvalikosta.", @@ -180,6 +182,7 @@ OC.L10N.register( "More" : "Enemmän", "Less" : "Vähemmän", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Lokitiedosto on kooltaan yli 100 megatavua. Sen lataaminen saattaa kestää hetken.", + "What to log" : "Mitä kerätään lokiin", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLitea käytetään tietokantana. Suuria asennuksia varten on suositeltavaa vaihtaa muuhun tietokantaan.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Varsinkin työpöytäsovelluksen tiedostosynkronointia käyttäessä SQLiten käyttö ei ole suositeltavaa.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Käytä komentorivityökalua toiseen tietokantaan migraation yhteydessä: 'occ db:convert-type', tai lue toki myös dokumentaatio ↗.", diff --git a/settings/l10n/fi_FI.json b/settings/l10n/fi_FI.json index 233e8b6386c..a517c3d2f16 100644 --- a/settings/l10n/fi_FI.json +++ b/settings/l10n/fi_FI.json @@ -152,7 +152,9 @@ "Use system's cron service to call the cron.php file every 15 minutes." : "Käytä järjestelmän cron-palvelua cron.php-tiedoston kutsumista varten 15 minuutin välein.", "Enable server-side encryption" : "Käytä palvelinpään salausta", "Please read carefully before activating server-side encryption: " : "Lue tarkasti, ennen kuin otat palvelinpään salauksen käyttöön:", + "Encryption alone does not guarantee security of the system. Please see ownCloud documentation for more information about how the encryption app works, and the supported use cases." : "Salaaminen pelkästään ei takaa järjestelmän tietoturvaa. Tutustu ownCloudin dokumentaation saadaksesi lisätietoja salaussovelluksen toiminnasta ja tuetuista käyttötapauksista.", "Be aware that encryption always increases the file size." : "Ota huomioon, että salaus kasvattaa aina tiedostojen kokoa.", + "It is always good to create regular backups of your data, in case of encryption make sure to backup the encryption keys along with your data." : "Säännöllisten varmuuskopioiden ottaminen on erittäin tärkeää. Jos olet ottanut salauksen käyttöön, huolehdi salausavainten varmuuskopioinnista.", "This is the final warning: Do you really want to enable encryption?" : "Tämä on viimeinen varoitus: haluatko varmasti ottaa salauksen käyttöön?", "Enable encryption" : "Käytä salausta", "No encryption module loaded, please enable an encryption module in the app menu." : "Salausmoduulia ei ole käytössä. Ota salausmoduuli käyttöön sovellusvalikosta.", @@ -178,6 +180,7 @@ "More" : "Enemmän", "Less" : "Vähemmän", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Lokitiedosto on kooltaan yli 100 megatavua. Sen lataaminen saattaa kestää hetken.", + "What to log" : "Mitä kerätään lokiin", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLitea käytetään tietokantana. Suuria asennuksia varten on suositeltavaa vaihtaa muuhun tietokantaan.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Varsinkin työpöytäsovelluksen tiedostosynkronointia käyttäessä SQLiten käyttö ei ole suositeltavaa.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Käytä komentorivityökalua toiseen tietokantaan migraation yhteydessä: 'occ db:convert-type', tai lue toki myös dokumentaatio ↗.", diff --git a/settings/l10n/hy.js b/settings/l10n/hy.js index bc0e467826b..01bf86bc863 100644 --- a/settings/l10n/hy.js +++ b/settings/l10n/hy.js @@ -17,6 +17,7 @@ OC.L10N.register( "Cancel" : "Չեղարկել", "Language" : "Լեզու", "Help translate" : "Օգնել թարգմանել", + "Username" : "Օգտանուն", "Group" : "Խումբ", "Other" : "Այլ" }, diff --git a/settings/l10n/hy.json b/settings/l10n/hy.json index 26cfdf5c9a7..4fc1882858d 100644 --- a/settings/l10n/hy.json +++ b/settings/l10n/hy.json @@ -15,6 +15,7 @@ "Cancel" : "Չեղարկել", "Language" : "Լեզու", "Help translate" : "Օգնել թարգմանել", + "Username" : "Օգտանուն", "Group" : "Խումբ", "Other" : "Այլ" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/settings/l10n/it.js b/settings/l10n/it.js index b01e4059e6d..4d73fe6100a 100644 --- a/settings/l10n/it.js +++ b/settings/l10n/it.js @@ -192,6 +192,7 @@ OC.L10N.register( "More" : "Altro", "Less" : "Meno", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Il file di log è più grande di 100MB. Scaricarlo potrebbe richiedere del tempo!", + "What to log" : "Cosa registrare", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite è utilizzato come database. Per installazioni più grandi consigliamo di passare a un motore di database diverso.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "In particolar modo, quando si utilizza il client desktop per la sincronizzazione dei file, l'uso di SQLite è sconsigliato.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Per migrare a un altro database, usa lo strumento da riga di comando: 'occ db:convert-type', o leggi la documentazione ↗.", diff --git a/settings/l10n/it.json b/settings/l10n/it.json index 1e9ae047bca..1090780f966 100644 --- a/settings/l10n/it.json +++ b/settings/l10n/it.json @@ -190,6 +190,7 @@ "More" : "Altro", "Less" : "Meno", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Il file di log è più grande di 100MB. Scaricarlo potrebbe richiedere del tempo!", + "What to log" : "Cosa registrare", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite è utilizzato come database. Per installazioni più grandi consigliamo di passare a un motore di database diverso.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "In particolar modo, quando si utilizza il client desktop per la sincronizzazione dei file, l'uso di SQLite è sconsigliato.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Per migrare a un altro database, usa lo strumento da riga di comando: 'occ db:convert-type', o leggi la documentazione ↗.", diff --git a/settings/l10n/ja.js b/settings/l10n/ja.js index 6ebb5e96311..f5204159125 100644 --- a/settings/l10n/ja.js +++ b/settings/l10n/ja.js @@ -192,6 +192,7 @@ OC.L10N.register( "More" : "もっと見る", "Less" : "閉じる", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "ログファイルが100MB以上あります。ダウンロードに時間がかかります!", + "What to log" : "ログ出力対象", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLiteがデータベースとして使用されています。大規模な運用では別のデータベースに切り替えることをお勧めします。", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "特にデスクトップクライアントをファイル同期に使用する場合,SQLiteは非推奨です.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "他のデータベースに移行する場合はコマンドラインツール: 'occ db:convert-type' を使ってください。 ドキュメント ↗を参照してください。", diff --git a/settings/l10n/ja.json b/settings/l10n/ja.json index 7a60706f723..5222cd8ec13 100644 --- a/settings/l10n/ja.json +++ b/settings/l10n/ja.json @@ -190,6 +190,7 @@ "More" : "もっと見る", "Less" : "閉じる", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "ログファイルが100MB以上あります。ダウンロードに時間がかかります!", + "What to log" : "ログ出力対象", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLiteがデータベースとして使用されています。大規模な運用では別のデータベースに切り替えることをお勧めします。", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "特にデスクトップクライアントをファイル同期に使用する場合,SQLiteは非推奨です.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "他のデータベースに移行する場合はコマンドラインツール: 'occ db:convert-type' を使ってください。 ドキュメント ↗を参照してください。", diff --git a/settings/l10n/sq.js b/settings/l10n/sq.js index fc7f21390ec..7addd9d7d3e 100644 --- a/settings/l10n/sq.js +++ b/settings/l10n/sq.js @@ -188,6 +188,7 @@ OC.L10N.register( "More" : "Më tepër", "Less" : "Më pak", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Kartela regjistër është më e madhe se 100 MB. Shkarkimi i saj mund të hajë ca kohë!", + "What to log" : "Ç’të regjistrohet", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "Si bazë të dhënash përdoret SQLite. Për instalime më të ngarkuara, këshillojmë të kalohet në një program tjetër baze të dhënash.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Përdorimi i SQLite-it nuk këshillohet veçanërisht kur përdoret klienti desktop për njëkohësim kartelash.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Për të kaluar te një tjetër bazë të dhënash përdorni mjetin rresht urdhrash: 'occ db:convert-type', ose shihni dokumentimin ↗.", diff --git a/settings/l10n/sq.json b/settings/l10n/sq.json index 912b93e3fe1..c5017a053a5 100644 --- a/settings/l10n/sq.json +++ b/settings/l10n/sq.json @@ -186,6 +186,7 @@ "More" : "Më tepër", "Less" : "Më pak", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Kartela regjistër është më e madhe se 100 MB. Shkarkimi i saj mund të hajë ca kohë!", + "What to log" : "Ç’të regjistrohet", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "Si bazë të dhënash përdoret SQLite. Për instalime më të ngarkuara, këshillojmë të kalohet në një program tjetër baze të dhënash.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Përdorimi i SQLite-it nuk këshillohet veçanërisht kur përdoret klienti desktop për njëkohësim kartelash.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Për të kaluar te një tjetër bazë të dhënash përdorni mjetin rresht urdhrash: 'occ db:convert-type', ose shihni dokumentimin ↗.", -- GitLab From a1704c86233312c4574bc368b78b73fb6b605c2b Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Sun, 13 Sep 2015 23:23:42 +0100 Subject: [PATCH 114/344] Render external storages list in JS --- .../controller/storagescontroller.php | 14 ++ apps/files_external/js/settings.js | 208 +++++++++++------- apps/files_external/templates/settings.php | 67 ------ 3 files changed, 140 insertions(+), 149 deletions(-) diff --git a/apps/files_external/controller/storagescontroller.php b/apps/files_external/controller/storagescontroller.php index 048f3588ed7..c66bd902d8d 100644 --- a/apps/files_external/controller/storagescontroller.php +++ b/apps/files_external/controller/storagescontroller.php @@ -255,6 +255,20 @@ abstract class StoragesController extends Controller { } } + /** + * Get all storage entries + * + * @return DataResponse + */ + public function index() { + $storages = $this->service->getAllStorages(); + + return new DataResponse( + $storages, + Http::STATUS_OK + ); + } + /** * Get an external storage entry. * diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index a839f396b9b..9b048ba193f 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -623,36 +623,9 @@ MountConfigListView.prototype = _.extend({ this._allBackends = this.$el.find('.selectBackend').data('configurations'); this._allAuthMechanisms = this.$el.find('#addMountPoint .authentication').data('mechanisms'); - //initialize hidden input field with list of users and groups - this.$el.find('tr:not(#addMountPoint)').each(function(i,tr) { - var $tr = $(tr); - var $applicable = $tr.find('.applicable'); - if ($applicable.length > 0) { - var groups = $applicable.data('applicable-groups'); - var groupsId = []; - $.each(groups, function () { - groupsId.push(this + '(group)'); - }); - var users = $applicable.data('applicable-users'); - if (users.indexOf('all') > -1 || users === '') { - $tr.find('.applicableUsers').val(''); - } else { - $tr.find('.applicableUsers').val(groupsId.concat(users).join(',')); - } - } - }); - - addSelect2(this.$el.find('tr:not(#addMountPoint) .applicableUsers'), this._userListLimit); - this.$el.tooltip({ - selector: '.status span', - container: 'body' - }); - this._initEvents(); - this.$el.find('tbody tr:not(#addMountPoint)').each(function(i, tr) { - self.recheckStorageConfig($(tr)); - }); + this.loadStorages(); }, /** @@ -661,7 +634,7 @@ MountConfigListView.prototype = _.extend({ */ whenSelectBackend: function(callback) { this.$el.find('tbody tr:not(#addMountPoint)').each(function(i, tr) { - var backend = $(tr).find('.backend').data('class'); + var backend = $(tr).find('.backend').data('identifier'); callback($(tr), backend); }); this.on('selectBackend', callback); @@ -725,57 +698,15 @@ MountConfigListView.prototype = _.extend({ _onSelectBackend: function(event) { var $target = $(event.target); - var $el = this.$el; var $tr = $target.closest('tr'); - $el.find('tbody').append($tr.clone()); - $el.find('tbody tr').last().find('.mountPoint input').val(''); - $tr.data('constructing', true); - var selected = $target.find('option:selected').text(); - var backend = $target.val(); - $tr.find('.backend').text(selected); - if ($tr.find('.mountPoint input').val() === '') { - $tr.find('.mountPoint input').val(this._suggestMountPoint(selected)); - } - $tr.addClass(backend); - $tr.find('.backend').data('class', backend); - var backendConfiguration = this._allBackends[backend]; - - var selectAuthMechanism = $(''); - $.each(this._allAuthMechanisms, function(authClass, authMechanism) { - if (backendConfiguration['authSchemes'][authMechanism['scheme']]) { - selectAuthMechanism.append( - $('') - ); - } - }); - $tr.find('td.authentication').append(selectAuthMechanism); - - var $td = $tr.find('td.configuration'); - $.each(backendConfiguration['configuration'], _.partial(this.writeParameterInput, $td)); - - this.trigger('selectBackend', $tr, backend); - selectAuthMechanism.trigger('change'); // generate configuration parameters for auth mechanism - - var priorityEl = $(''); - $tr.append(priorityEl); - $td.children().not('[type=hidden]').first().focus(); + var storageConfig = new this._storageConfigClass(); + storageConfig.mountPoint = $tr.find('.mountPoint input').val(); + storageConfig.backend = $target.val(); - // FIXME default backend mount options - $tr.find('input.mountOptions').val(JSON.stringify({ - 'encrypt': true, - 'previews': true, - 'filesystem_check_changes': 1 - })); - - $tr.find('td').last().attr('class', 'remove'); - $tr.find('td.mountOptionsToggle').removeClass('hidden'); - $tr.find('td').last().removeAttr('style'); - $tr.removeAttr('id'); - $target.remove(); - addSelect2($tr.find('.applicableUsers'), this._userListLimit); + $tr = this.newStorage(storageConfig); - $tr.removeData('constructing'); + $tr.find('td.configuration').children().not('[type=hidden]').first().focus(); this.saveStorageConfig($tr); }, @@ -802,6 +733,118 @@ MountConfigListView.prototype = _.extend({ } }, + /** + * Create a config row for a new storage + * + * @param {StorageConfig} storageConfig storage config to pull values from + * @return {jQuery} created row + */ + newStorage: function(storageConfig) { + var mountPoint = storageConfig.mountPoint; + var backend = this._allBackends[storageConfig.backend]; + + // FIXME: Replace with a proper Handlebar template + var $tr = this.$el.find('tr#addMountPoint'); + this.$el.find('tbody').append($tr.clone()); + + $tr.find('td').last().attr('class', 'remove'); + $tr.find('td.mountOptionsToggle').removeClass('hidden'); + $tr.find('td').last().removeAttr('style'); + $tr.removeAttr('id'); + $tr.find('select#selectBackend'); + addSelect2($tr.find('.applicableUsers'), this._userListLimit); + + $tr.data('constructing', true); + + if (storageConfig.id) { + $tr.data('id', storageConfig.id); + } + + $tr.find('.backend').text(backend.name); + if (mountPoint === '') { + mountPoint = this._suggestMountPoint(backend.name); + } + $tr.find('.mountPoint input').val(mountPoint); + $tr.addClass(backend.identifier); + $tr.find('.backend').data('identifier', backend.identifier); + + var selectAuthMechanism = $(''); + $.each(this._allAuthMechanisms, function(authIdentifier, authMechanism) { + if (backend.authSchemes[authMechanism.scheme]) { + selectAuthMechanism.append( + $('') + ); + } + }); + if (storageConfig.authMechanism) { + selectAuthMechanism.val(storageConfig.authMechanism); + } + $tr.find('td.authentication').append(selectAuthMechanism); + + var $td = $tr.find('td.configuration'); + $.each(backend.configuration, _.partial(this.writeParameterInput, $td)); + + this.trigger('selectBackend', $tr, backend.identifier); + + selectAuthMechanism.trigger('change'); // generate configuration parameters for auth mechanism + + if (storageConfig.backendOptions) { + $td.children().each(function() { + var input = $(this); + input.val(storageConfig.backendOptions[input.data('parameter')]); + highlightInput(input); + }); + } + + var priorityEl = $(''); + $tr.append(priorityEl); + + if (storageConfig.mountOptions) { + $tr.find('input.mountOptions').val(JSON.stringify(storageConfig.mountOptions)); + } else { + // FIXME default backend mount options + $tr.find('input.mountOptions').val(JSON.stringify({ + 'encrypt': true, + 'previews': true, + 'filesystem_check_changes': 1 + })); + } + + $tr.removeData('constructing'); + return $tr; + }, + + /** + * Load storages into config rows + */ + loadStorages: function() { + var self = this; + + var url = this._storageConfigClass.prototype._url; + + $.ajax({ + type: 'GET', + url: OC.generateUrl(url), + contentType: 'application/json', + success: function(result) { + $.each(result, function(i, storageParams) { + storageParams.mountPoint = storageParams.mountPoint.substr(1); // trim leading slash + var storageConfig = new self._storageConfigClass(); + _.extend(storageConfig, storageParams); + var $tr = self.newStorage(storageConfig); + self.recheckStorageConfig($tr); + }); + } + }); + }, + + /** + * @param {jQuery} $td + * @param {string} parameter + * @param {string} placeholder + * @param {Array} classes + * @return {jQuery} newly created input + */ writeParameterInput: function($td, parameter, placeholder, classes) { classes = $.isArray(classes) ? classes : []; classes.push('added'); @@ -822,6 +865,7 @@ MountConfigListView.prototype = _.extend({ } highlightInput(newElement); $td.append(newElement); + return newElement; }, /** @@ -831,14 +875,14 @@ MountConfigListView.prototype = _.extend({ * @return {OCA.External.StorageConfig} storage model instance */ getStorageConfig: function($tr) { - var storageId = parseInt($tr.attr('data-id'), 10); + var storageId = $tr.data('id'); if (!storageId) { // new entry storageId = null; } var storage = new this._storageConfigClass(storageId); storage.mountPoint = $tr.find('.mountPoint input').val(); - storage.backend = $tr.find('.backend').data('class'); + storage.backend = $tr.find('.backend').data('identifier'); storage.authMechanism = $tr.find('.selectAuthMechanism').val(); var classOptions = {}; @@ -951,8 +995,8 @@ MountConfigListView.prototype = _.extend({ if (concurrentTimer === undefined || $tr.data('save-timer') === concurrentTimer ) { - self.updateStatus($tr, result.status, result.statusMessage); - $tr.attr('data-id', result.id); + self.updateStatus($tr, result.status); + $tr.data('id', result.id); if (_.isFunction(callback)) { callback(storage); @@ -1054,12 +1098,12 @@ MountConfigListView.prototype = _.extend({ } return defaultMountPoint + append; }, - + /** * Toggles the mount options dropdown * * @param {Object} $tr configuration row - */ + */ _showMountOptionsDropdown: function($tr) { if (this._preventNextDropdown) { // prevented because the click was on the toggle diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index cebf6cc4de0..14136a9bad7 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -70,73 +70,6 @@ - - - - - - - - getBackend()->getText()); ?> - - - - - - getBackendOptions(); - foreach ($storage->getBackend()->getParameters() as $parameter) { - writeParameterInput($parameter, $options); - } - foreach ($storage->getAuthMechanism()->getParameters() as $parameter) { - writeParameterInput($parameter, $options, ['auth-param']); - } - ?> - - - - - - - - <?php p($l->t('Advanced settings')); ?> - - - - - - - <?php p($l->t('Delete')); ?> - - - -- GitLab From 28876bf46363116218c48021ddf556c53d5256f5 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Mon, 14 Sep 2015 13:57:49 +0100 Subject: [PATCH 115/344] Display applicable global storages in personal mount list --- apps/files_external/appinfo/routes.php | 1 + .../userglobalstoragescontroller.php | 121 ++++++++++++++++++ apps/files_external/js/settings.js | 31 +++++ apps/files_external/personal.php | 26 +--- apps/files_external/settings.php | 31 +---- apps/files_external/templates/settings.php | 34 ++++- 6 files changed, 187 insertions(+), 57 deletions(-) create mode 100644 apps/files_external/controller/userglobalstoragescontroller.php diff --git a/apps/files_external/appinfo/routes.php b/apps/files_external/appinfo/routes.php index 39ded1dc2ec..e66c010a8cf 100644 --- a/apps/files_external/appinfo/routes.php +++ b/apps/files_external/appinfo/routes.php @@ -36,6 +36,7 @@ namespace OCA\Files_External\AppInfo; 'resources' => array( 'global_storages' => array('url' => '/globalstorages'), 'user_storages' => array('url' => '/userstorages'), + 'user_global_storages' => array('url' => '/userglobalstorages'), ), 'routes' => array( array( diff --git a/apps/files_external/controller/userglobalstoragescontroller.php b/apps/files_external/controller/userglobalstoragescontroller.php new file mode 100644 index 00000000000..b77e23104e4 --- /dev/null +++ b/apps/files_external/controller/userglobalstoragescontroller.php @@ -0,0 +1,121 @@ + + * + * @copyright Copyright (c) 2015, 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 OCA\Files_External\Controller; + +use \OCP\IRequest; +use \OCP\IL10N; +use \OCP\AppFramework\Http\DataResponse; +use \OCP\AppFramework\Controller; +use \OCP\AppFramework\Http; +use \OCA\Files_external\Service\UserGlobalStoragesService; +use \OCA\Files_external\NotFoundException; +use \OCA\Files_external\Lib\StorageConfig; +use \OCA\Files_External\Lib\Backend\Backend; + +/** + * User global storages controller + */ +class UserGlobalStoragesController extends StoragesController { + /** + * Creates a new user global storages controller. + * + * @param string $AppName application name + * @param IRequest $request request object + * @param IL10N $l10n l10n service + * @param UserGlobalStoragesService $userGlobalStoragesService storage service + */ + public function __construct( + $AppName, + IRequest $request, + IL10N $l10n, + UserGlobalStoragesService $userGlobalStoragesService + ) { + parent::__construct( + $AppName, + $request, + $l10n, + $userGlobalStoragesService + ); + } + + /** + * Get all storage entries + * + * @return DataResponse + * + * @NoAdminRequired + */ + public function index() { + $storages = $this->service->getAllStorages(); + + // remove configuration data, this must be kept private + foreach ($storages as $storage) { + $this->sanitizeStorage($storage); + } + + return new DataResponse( + $storages, + Http::STATUS_OK + ); + } + + /** + * Get an external storage entry. + * + * @param int $id storage id + * @return DataResponse + * + * @NoAdminRequired + */ + public function show($id) { + try { + $storage = $this->service->getStorage($id); + + $this->updateStorageStatus($storage); + } catch (NotFoundException $e) { + return new DataResponse( + [ + 'message' => (string)$this->l10n->t('Storage with id "%i" not found', array($id)) + ], + Http::STATUS_NOT_FOUND + ); + } + + $this->sanitizeStorage($storage); + + return new DataResponse( + $storage, + Http::STATUS_OK + ); + } + + /** + * Remove sensitive data from a StorageConfig before returning it to the user + * + * @param StorageConfig $storage + */ + protected function sanitizeStorage(StorageConfig $storage) { + $storage->setBackendOptions([]); + $storage->setMountOptions([]); + } + +} diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 9b048ba193f..c9badb2f728 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -820,6 +820,37 @@ MountConfigListView.prototype = _.extend({ loadStorages: function() { var self = this; + if (this._isPersonal) { + // load userglobal storages + $.ajax({ + type: 'GET', + url: OC.generateUrl('apps/files_external/userglobalstorages'), + contentType: 'application/json', + success: function(result) { + $.each(result, function(i, storageParams) { + storageParams.mountPoint = storageParams.mountPoint.substr(1); // trim leading slash + var storageConfig = new self._storageConfigClass(); + _.extend(storageConfig, storageParams); + var $tr = self.newStorage(storageConfig); + + // userglobal storages must be at the top of the list + $tr.detach(); + self.$el.prepend($tr); + + var $authentication = $tr.find('.authentication'); + $authentication.text($authentication.find('select option:selected').text()); + + // userglobal storages do not expose configuration data + $tr.find('.configuration').text(t('files_external', 'Admin defined')); + + // disable any other inputs + $tr.find('.mountOptionsToggle, .remove').empty(); + $tr.find('input, select, button').attr('disabled', 'disabled'); + }); + } + }); + } + var url = this._storageConfigClass.prototype._url; $.ajax({ diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php index df15c3bd258..05196a58905 100644 --- a/apps/files_external/personal.php +++ b/apps/files_external/personal.php @@ -32,31 +32,11 @@ $appContainer = \OC_Mount_Config::$app->getContainer(); $backendService = $appContainer->query('OCA\Files_External\Service\BackendService'); $userStoragesService = $appContainer->query('OCA\Files_external\Service\UserStoragesService'); -OCP\Util::addScript('files_external', 'settings'); -OCP\Util::addStyle('files_external', 'settings'); - -$backends = array_filter($backendService->getAvailableBackends(), function($backend) { - return $backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL); -}); -$authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) { - return $authMechanism->isVisibleFor(BackendService::VISIBILITY_PERSONAL); -}); -foreach ($backends as $backend) { - if ($backend->getCustomJs()) { - \OCP\Util::addScript('files_external', $backend->getCustomJs()); - } -} -foreach ($authMechanisms as $authMechanism) { - if ($authMechanism->getCustomJs()) { - \OCP\Util::addScript('files_external', $authMechanism->getCustomJs()); - } -} - $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled()); -$tmpl->assign('isAdminPage', false); +$tmpl->assign('visibilityType', BackendService::VISIBILITY_PERSONAL); $tmpl->assign('storages', $userStoragesService->getStorages()); $tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends())); -$tmpl->assign('backends', $backends); -$tmpl->assign('authMechanisms', $authMechanisms); +$tmpl->assign('backends', $backendService->getAvailableBackends()); +$tmpl->assign('authMechanisms', $backendService->getAuthMechanisms()); return $tmpl->fetchPage(); diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php index 03ed363bdb2..50d47d667fd 100644 --- a/apps/files_external/settings.php +++ b/apps/files_external/settings.php @@ -35,40 +35,15 @@ $appContainer = \OC_Mount_Config::$app->getContainer(); $backendService = $appContainer->query('OCA\Files_External\Service\BackendService'); $globalStoragesService = $appContainer->query('OCA\Files_external\Service\GlobalStoragesService'); -OCP\Util::addScript('files_external', 'settings'); -OCP\Util::addStyle('files_external', 'settings'); - \OC_Util::addVendorScript('select2/select2'); \OC_Util::addVendorStyle('select2/select2'); -$backends = array_filter($backendService->getAvailableBackends(), function($backend) { - return $backend->isVisibleFor(BackendService::VISIBILITY_ADMIN); -}); -$authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) { - return $authMechanism->isVisibleFor(BackendService::VISIBILITY_ADMIN); -}); -foreach ($backends as $backend) { - if ($backend->getCustomJs()) { - \OCP\Util::addScript('files_external', $backend->getCustomJs()); - } -} -foreach ($authMechanisms as $authMechanism) { - if ($authMechanism->getCustomJs()) { - \OCP\Util::addScript('files_external', $authMechanism->getCustomJs()); - } -} - -$userBackends = array_filter($backendService->getAvailableBackends(), function($backend) { - return $backend->isAllowedVisibleFor(BackendService::VISIBILITY_PERSONAL); -}); - $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled()); -$tmpl->assign('isAdminPage', true); +$tmpl->assign('visibilityType', BackendService::VISIBILITY_ADMIN); $tmpl->assign('storages', $globalStoragesService->getStorages()); -$tmpl->assign('backends', $backends); -$tmpl->assign('authMechanisms', $authMechanisms); -$tmpl->assign('userBackends', $userBackends); +$tmpl->assign('backends', $backendService->getAvailableBackends()); +$tmpl->assign('authMechanisms', $backendService->getAuthMechanisms()); $tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends())); $tmpl->assign('allowUserMounting', $backendService->isUserMountingAllowed()); return $tmpl->fetchPage(); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 14136a9bad7..f7caf3d2caa 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -3,6 +3,21 @@ use \OCA\Files_External\Lib\DefinitionParameter; use \OCA\Files_External\Service\BackendService; + script('files_external', 'settings'); + style('files_external', 'settings'); + + // load custom JS + foreach ($_['backends'] as $backend) { + if ($backend->getCustomJs()) { + script('files_external', $backend->getCustomJs()); + } + } + foreach ($_['authMechanisms'] as $authMechanism) { + if ($authMechanism->getCustomJs()) { + script('files_external', $authMechanism->getCustomJs()); + } + } + function writeParameterInput($parameter, $options, $classes = []) { $value = ''; if (isset($options[$parameter->getName()])) { @@ -56,7 +71,7 @@

      t('External Storage')); ?>

      '')) print_unescaped(''.$_['dependencies'].''); ?> - '> +
      '> @@ -64,7 +79,7 @@ - '.$l->t('Available for').''); ?> + '.$l->t('Available for').''); ?> @@ -84,7 +99,9 @@ t('Add storage')); ?> isVisibleFor($_['visibilityType']); + }); uasort($sortedBackends, function($a, $b) { return strcasecmp($a->getText(), $b->getText()); }); @@ -97,7 +114,7 @@ - + @@ -122,7 +139,7 @@
      t('External storage')); ?> t('Authentication')); ?> t('Configuration')); ?>   
      '>

      - +
      /> @@ -130,7 +147,12 @@

      class="hidden"> t('Allow users to mount the following external storage')); ?>
      - + isAllowedVisibleFor(BackendService::VISIBILITY_PERSONAL); + }); + ?> + getDeprecateTo()): ?> -- GitLab From 2efffb810d89f56cf2e128b536b79925bd5f9638 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Mon, 14 Sep 2015 20:21:16 +0100 Subject: [PATCH 116/344] Load applicable users/groups correctly --- apps/files_external/js/settings.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index c9badb2f728..d2ff23e89b8 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -796,6 +796,19 @@ MountConfigListView.prototype = _.extend({ }); } + var applicable = []; + if (storageConfig.applicableUsers) { + applicable = applicable.concat(storageConfig.applicableUsers); + } + if (storageConfig.applicableGroups) { + applicable = applicable.concat( + _.map(storageConfig.applicableGroups, function(group) { + return group+'(group)'; + }) + ); + } + $tr.find('.applicableUsers').val(applicable).trigger('change'); + var priorityEl = $(''); $tr.append(priorityEl); -- GitLab From 8f4b780a9055e9ce26a7c147fd4ee70dde8f02dc Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Mon, 14 Sep 2015 20:31:24 +0100 Subject: [PATCH 117/344] Fix external storage priority logic --- apps/files_external/controller/userglobalstoragescontroller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_external/controller/userglobalstoragescontroller.php b/apps/files_external/controller/userglobalstoragescontroller.php index b77e23104e4..c6f777763e8 100644 --- a/apps/files_external/controller/userglobalstoragescontroller.php +++ b/apps/files_external/controller/userglobalstoragescontroller.php @@ -65,7 +65,7 @@ class UserGlobalStoragesController extends StoragesController { * @NoAdminRequired */ public function index() { - $storages = $this->service->getAllStorages(); + $storages = $this->service->getUniqueStorages(); // remove configuration data, this must be kept private foreach ($storages as $storage) { -- GitLab From 6a2e7632d17eb2b239aad068ba1dcd1252d6ae0f Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Mon, 14 Sep 2015 22:21:42 +0100 Subject: [PATCH 118/344] Fix JS unit tests --- apps/files_external/js/settings.js | 3 +-- apps/files_external/tests/js/settingsSpec.js | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index d2ff23e89b8..586b9af7a88 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -624,8 +624,6 @@ MountConfigListView.prototype = _.extend({ this._allAuthMechanisms = this.$el.find('#addMountPoint .authentication').data('mechanisms'); this._initEvents(); - - this.loadStorages(); }, /** @@ -1194,6 +1192,7 @@ $(document).ready(function() { var mountConfigListView = new MountConfigListView($('#externalStorage'), { encryptionEnabled: encryptionEnabled }); + mountConfigListView.loadStorages(); $('#sslCertificate').on('click', 'td.remove>img', function() { var $tr = $(this).closest('tr'); diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js index 67a81277124..3d0168898ca 100644 --- a/apps/files_external/tests/js/settingsSpec.js +++ b/apps/files_external/tests/js/settingsSpec.js @@ -54,7 +54,8 @@ describe('OCA.External.Settings tests', function() { // within the DOM by the server template $('#externalStorage .selectBackend:first').data('configurations', { '\\OC\\TestBackend': { - 'backend': 'Test Backend Name', + 'identifier': '\\OC\\TestBackend', + 'name': 'Test Backend', 'configuration': { 'field1': 'Display Name 1', 'field2': '&Display Name 2' @@ -65,7 +66,8 @@ describe('OCA.External.Settings tests', function() { 'priority': 11 }, '\\OC\\AnotherTestBackend': { - 'backend': 'Another Test Backend Name', + 'identifier': '\\OC\\AnotherTestBackend', + 'name': 'Another Test Backend', 'configuration': { 'field1': 'Display Name 1', 'field2': '&Display Name 2' @@ -80,6 +82,7 @@ describe('OCA.External.Settings tests', function() { $('#externalStorage #addMountPoint .authentication:first').data('mechanisms', { 'mechanism1': { + 'identifier': 'mechanism1', 'name': 'Mechanism 1', 'configuration': { }, -- GitLab From be8afc2c12efcc6734ce813e12fefeb792d04867 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Tue, 15 Sep 2015 14:38:28 +0100 Subject: [PATCH 119/344] Reset mountpoint input field when creating new mount --- apps/files_external/js/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 586b9af7a88..3152c644b32 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -701,6 +701,7 @@ MountConfigListView.prototype = _.extend({ var storageConfig = new this._storageConfigClass(); storageConfig.mountPoint = $tr.find('.mountPoint input').val(); storageConfig.backend = $target.val(); + $tr.find('.mountPoint input').val(''); $tr = this.newStorage(storageConfig); -- GitLab From c5966ed21b56f083e090a0b1b48e567383e7ee39 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Tue, 20 Oct 2015 13:26:46 +0100 Subject: [PATCH 120/344] Only set value if it exists in the StorageConfig --- apps/files_external/js/settings.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 3152c644b32..e16944eaa19 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -790,8 +790,11 @@ MountConfigListView.prototype = _.extend({ if (storageConfig.backendOptions) { $td.children().each(function() { var input = $(this); - input.val(storageConfig.backendOptions[input.data('parameter')]); - highlightInput(input); + var val = storageConfig.backendOptions[input.data('parameter')]; + if (val !== undefined) { + input.val(storageConfig.backendOptions[input.data('parameter')]); + highlightInput(input); + } }); } -- GitLab From ee7128b43549ed2ce1e8a96c132503809ac87ba9 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Tue, 20 Oct 2015 13:35:45 +0100 Subject: [PATCH 121/344] Clear highlight on RSA public key generation --- apps/files_external/js/public_key.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_external/js/public_key.js b/apps/files_external/js/public_key.js index a8546067452..e35d7ad3789 100644 --- a/apps/files_external/js/public_key.js +++ b/apps/files_external/js/public_key.js @@ -33,7 +33,7 @@ $(document).ready(function() { $.post(OC.filePath('files_external', 'ajax', 'public_key.php'), {}, function(result) { if (result && result.status === 'success') { - $(config).find('[data-parameter="public_key"]').val(result.data.public_key); + $(config).find('[data-parameter="public_key"]').val(result.data.public_key).keyup(); $(config).find('[data-parameter="private_key"]').val(result.data.private_key); OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() { // Nothing to do -- GitLab From 2321cc4854257ba760510e4111f071150b26c81a Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Sun, 22 Nov 2015 01:54:53 -0500 Subject: [PATCH 122/344] [tx-robot] updated from transifex --- apps/files/l10n/lt_LT.js | 8 +++++--- apps/files/l10n/lt_LT.json | 8 +++++--- apps/files/l10n/nds.js | 4 ++++ apps/files/l10n/nds.json | 4 ++++ apps/files_external/l10n/lt_LT.js | 1 + apps/files_external/l10n/lt_LT.json | 1 + apps/files_trashbin/l10n/nds.js | 1 + apps/files_trashbin/l10n/nds.json | 1 + apps/user_ldap/l10n/es.js | 1 + apps/user_ldap/l10n/es.json | 1 + apps/user_ldap/l10n/lt_LT.js | 3 +++ apps/user_ldap/l10n/lt_LT.json | 3 +++ core/l10n/lt_LT.js | 1 + core/l10n/lt_LT.json | 1 + core/l10n/nds.js | 4 ++++ core/l10n/nds.json | 4 ++++ lib/l10n/es.js | 2 ++ lib/l10n/es.json | 2 ++ lib/l10n/lt_LT.js | 5 +++++ lib/l10n/lt_LT.json | 5 +++++ settings/l10n/cs_CZ.js | 1 + settings/l10n/cs_CZ.json | 1 + settings/l10n/lt_LT.js | 14 ++++++++++++++ settings/l10n/lt_LT.json | 14 ++++++++++++++ 24 files changed, 84 insertions(+), 6 deletions(-) diff --git a/apps/files/l10n/lt_LT.js b/apps/files/l10n/lt_LT.js index ac7084cfc2d..13e7a03e45b 100644 --- a/apps/files/l10n/lt_LT.js +++ b/apps/files/l10n/lt_LT.js @@ -75,8 +75,6 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų"], "Favorited" : "Pažymėta mėgstamu", "Favorite" : "Mėgiamas", - "Text file" : "Teksto failas", - "New text file.txt" : "Naujas tekstas file.txt", "Folder" : "Katalogas", "New folder" : "Naujas aplankas", "{newname} already exists" : "{newname} jau egzistuoja", @@ -106,6 +104,8 @@ OC.L10N.register( "Maximum upload size" : "Maksimalus įkeliamo failo dydis", "max. possible: " : "maks. galima:", "Save" : "Išsaugoti", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Su PHP-FPM atnaujinimai gali užtrukti apie 5min.", + "Missing permissions to edit from here." : "Draudžiama iš čia redaguoti", "Settings" : "Nustatymai", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Naudokite šį adresą, kad pasiektumėte savo failus per WebDAV", @@ -119,6 +119,8 @@ OC.L10N.register( "Files are being scanned, please wait." : "Skenuojami failai, prašome palaukti.", "Currently scanning" : "Šiuo metu skenuojama", "No favorites" : "Nėra mėgstamiausių", - "Files and folders you mark as favorite will show up here" : "Failai ir aplankai, kuriuos pažymite mėgstamais, atsiras čia" + "Files and folders you mark as favorite will show up here" : "Failai ir aplankai, kuriuos pažymite mėgstamais, atsiras čia", + "Text file" : "Teksto failas", + "New text file.txt" : "Naujas tekstas file.txt" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/apps/files/l10n/lt_LT.json b/apps/files/l10n/lt_LT.json index aef54469542..c6e4a35c815 100644 --- a/apps/files/l10n/lt_LT.json +++ b/apps/files/l10n/lt_LT.json @@ -73,8 +73,6 @@ "_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų"], "Favorited" : "Pažymėta mėgstamu", "Favorite" : "Mėgiamas", - "Text file" : "Teksto failas", - "New text file.txt" : "Naujas tekstas file.txt", "Folder" : "Katalogas", "New folder" : "Naujas aplankas", "{newname} already exists" : "{newname} jau egzistuoja", @@ -104,6 +102,8 @@ "Maximum upload size" : "Maksimalus įkeliamo failo dydis", "max. possible: " : "maks. galima:", "Save" : "Išsaugoti", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Su PHP-FPM atnaujinimai gali užtrukti apie 5min.", + "Missing permissions to edit from here." : "Draudžiama iš čia redaguoti", "Settings" : "Nustatymai", "WebDAV" : "WebDAV", "Use this address to access your Files via WebDAV" : "Naudokite šį adresą, kad pasiektumėte savo failus per WebDAV", @@ -117,6 +117,8 @@ "Files are being scanned, please wait." : "Skenuojami failai, prašome palaukti.", "Currently scanning" : "Šiuo metu skenuojama", "No favorites" : "Nėra mėgstamiausių", - "Files and folders you mark as favorite will show up here" : "Failai ir aplankai, kuriuos pažymite mėgstamais, atsiras čia" + "Files and folders you mark as favorite will show up here" : "Failai ir aplankai, kuriuos pažymite mėgstamais, atsiras čia", + "Text file" : "Teksto failas", + "New text file.txt" : "Naujas tekstas file.txt" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);" } \ No newline at end of file diff --git a/apps/files/l10n/nds.js b/apps/files/l10n/nds.js index 9b28220ae43..37043dbe6c1 100644 --- a/apps/files/l10n/nds.js +++ b/apps/files/l10n/nds.js @@ -3,7 +3,11 @@ OC.L10N.register( { "Files" : "Dateien", "Delete" : "Löschen", + "Details" : "Details", + "Error" : "Fehler", "Name" : "Name", + "New folder" : "Neuer Ordner", + "Upload" : "Hochladen", "Settings" : "Einstellungen", "WebDAV" : "WebDAV" }, diff --git a/apps/files/l10n/nds.json b/apps/files/l10n/nds.json index 4ab8de68b35..dbd6bad9573 100644 --- a/apps/files/l10n/nds.json +++ b/apps/files/l10n/nds.json @@ -1,7 +1,11 @@ { "translations": { "Files" : "Dateien", "Delete" : "Löschen", + "Details" : "Details", + "Error" : "Fehler", "Name" : "Name", + "New folder" : "Neuer Ordner", + "Upload" : "Hochladen", "Settings" : "Einstellungen", "WebDAV" : "WebDAV" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/apps/files_external/l10n/lt_LT.js b/apps/files_external/l10n/lt_LT.js index b6d334d792d..78d03a865f2 100644 --- a/apps/files_external/l10n/lt_LT.js +++ b/apps/files_external/l10n/lt_LT.js @@ -1,6 +1,7 @@ OC.L10N.register( "files_external", { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "Nepavyko atsiųsti užklausos žymės. Patikrinkite savo programos raktą ir paslaptį.", "External storage" : "Išorinė saugykla", "Personal" : "Asmeniniai", "Grant access" : "Suteikti priėjimą", diff --git a/apps/files_external/l10n/lt_LT.json b/apps/files_external/l10n/lt_LT.json index f1c46b145ee..fcb1f1f39bd 100644 --- a/apps/files_external/l10n/lt_LT.json +++ b/apps/files_external/l10n/lt_LT.json @@ -1,4 +1,5 @@ { "translations": { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "Nepavyko atsiųsti užklausos žymės. Patikrinkite savo programos raktą ir paslaptį.", "External storage" : "Išorinė saugykla", "Personal" : "Asmeniniai", "Grant access" : "Suteikti priėjimą", diff --git a/apps/files_trashbin/l10n/nds.js b/apps/files_trashbin/l10n/nds.js index b2dd9ff4ca6..8212e5210a9 100644 --- a/apps/files_trashbin/l10n/nds.js +++ b/apps/files_trashbin/l10n/nds.js @@ -2,6 +2,7 @@ OC.L10N.register( "files_trashbin", { "Delete" : "Löschen", + "Error" : "Fehler", "Name" : "Name" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_trashbin/l10n/nds.json b/apps/files_trashbin/l10n/nds.json index 45b0caa74ac..d15a7c583ac 100644 --- a/apps/files_trashbin/l10n/nds.json +++ b/apps/files_trashbin/l10n/nds.json @@ -1,5 +1,6 @@ { "translations": { "Delete" : "Löschen", + "Error" : "Fehler", "Name" : "Name" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/user_ldap/l10n/es.js b/apps/user_ldap/l10n/es.js index bfe48c28f99..e457978bcd7 100644 --- a/apps/user_ldap/l10n/es.js +++ b/apps/user_ldap/l10n/es.js @@ -24,6 +24,7 @@ OC.L10N.register( "Could not detect Base DN, please enter it manually." : "No se pudo detectar Base DN, por favor ingrésela manualmente.", "{nthServer}. Server" : "{nthServer}. servidor", "No object found in the given Base DN. Please revise." : "No se encuentra ningún objeto en la Base DN dada. Por favor revisar.", + "More than 1,000 directory entries available." : "Más de 1.000 entradas de directorios disponibles.", " entries available within the provided Base DN" : "entradas disponibles dentro de la BaseDN provista", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Un error ocurrió. Por favor revise la Base DN, también como la configuración de la conexión y credenciales.", "Do you really want to delete the current Server Configuration?" : "¿Realmente desea eliminar la configuración actual del servidor?", diff --git a/apps/user_ldap/l10n/es.json b/apps/user_ldap/l10n/es.json index c8d64f6b9d6..ebce66270f1 100644 --- a/apps/user_ldap/l10n/es.json +++ b/apps/user_ldap/l10n/es.json @@ -22,6 +22,7 @@ "Could not detect Base DN, please enter it manually." : "No se pudo detectar Base DN, por favor ingrésela manualmente.", "{nthServer}. Server" : "{nthServer}. servidor", "No object found in the given Base DN. Please revise." : "No se encuentra ningún objeto en la Base DN dada. Por favor revisar.", + "More than 1,000 directory entries available." : "Más de 1.000 entradas de directorios disponibles.", " entries available within the provided Base DN" : "entradas disponibles dentro de la BaseDN provista", "An error occurred. Please check the Base DN, as well as connection settings and credentials." : "Un error ocurrió. Por favor revise la Base DN, también como la configuración de la conexión y credenciales.", "Do you really want to delete the current Server Configuration?" : "¿Realmente desea eliminar la configuración actual del servidor?", diff --git a/apps/user_ldap/l10n/lt_LT.js b/apps/user_ldap/l10n/lt_LT.js index e9429c0de2a..a5b85499804 100644 --- a/apps/user_ldap/l10n/lt_LT.js +++ b/apps/user_ldap/l10n/lt_LT.js @@ -4,9 +4,12 @@ OC.L10N.register( "Failed to clear the mappings." : "Nepavyko išvalyti sąsajų.", "Failed to delete the server configuration" : "Nepavyko pašalinti serverio konfigūracijos", "The configuration is valid and the connection could be established!" : "Konfigūracija yra tinkama bei prisijungta sėkmingai!", + "No action specified" : "Nepasirinktas veiksmas", "Select groups" : "Pasirinkti grupes", "Do you really want to delete the current Server Configuration?" : "Ar tikrai norite ištrinti dabartinę serverio konfigūraciją?", "Confirm Deletion" : "Patvirtinkite trynimą", + "_%s group found_::_%s groups found_" : ["Rasta %s grupė","Rastos %s grupės","Rastos %s grupės"], + "_%s user found_::_%s users found_" : ["Rastas %s vartotojas","Rasti %s vartotojai","Rasti %s vartotojai"], "Server" : "Serveris", "Users" : "Vartotojai", "Groups" : "Grupės", diff --git a/apps/user_ldap/l10n/lt_LT.json b/apps/user_ldap/l10n/lt_LT.json index 19ca042b62f..68dfbc38b9c 100644 --- a/apps/user_ldap/l10n/lt_LT.json +++ b/apps/user_ldap/l10n/lt_LT.json @@ -2,9 +2,12 @@ "Failed to clear the mappings." : "Nepavyko išvalyti sąsajų.", "Failed to delete the server configuration" : "Nepavyko pašalinti serverio konfigūracijos", "The configuration is valid and the connection could be established!" : "Konfigūracija yra tinkama bei prisijungta sėkmingai!", + "No action specified" : "Nepasirinktas veiksmas", "Select groups" : "Pasirinkti grupes", "Do you really want to delete the current Server Configuration?" : "Ar tikrai norite ištrinti dabartinę serverio konfigūraciją?", "Confirm Deletion" : "Patvirtinkite trynimą", + "_%s group found_::_%s groups found_" : ["Rasta %s grupė","Rastos %s grupės","Rastos %s grupės"], + "_%s user found_::_%s users found_" : ["Rastas %s vartotojas","Rasti %s vartotojai","Rasti %s vartotojai"], "Server" : "Serveris", "Users" : "Vartotojai", "Groups" : "Grupės", diff --git a/core/l10n/lt_LT.js b/core/l10n/lt_LT.js index 1b9d4842913..829e6f9e957 100644 --- a/core/l10n/lt_LT.js +++ b/core/l10n/lt_LT.js @@ -6,6 +6,7 @@ OC.L10N.register( "Turned on maintenance mode" : "Įjungta priežiūros veiksena", "Turned off maintenance mode" : "Išjungta priežiūros veiksena", "Maintenance mode is kept active" : "Priežiūros veiksena yra aktyvi", + "Updating database schema" : "Atnaujinama duomenų bazės struktūra", "Updated database" : "Atnaujinta duomenų bazė", "Checked database schema update" : "Tikrinama duomenų bazės struktūra", "Checked database schema update for apps" : "Tikrinama duomenų bazės struktūra įskiepiams", diff --git a/core/l10n/lt_LT.json b/core/l10n/lt_LT.json index 8df5dc1ff48..f67b9d6cc00 100644 --- a/core/l10n/lt_LT.json +++ b/core/l10n/lt_LT.json @@ -4,6 +4,7 @@ "Turned on maintenance mode" : "Įjungta priežiūros veiksena", "Turned off maintenance mode" : "Išjungta priežiūros veiksena", "Maintenance mode is kept active" : "Priežiūros veiksena yra aktyvi", + "Updating database schema" : "Atnaujinama duomenų bazės struktūra", "Updated database" : "Atnaujinta duomenų bazė", "Checked database schema update" : "Tikrinama duomenų bazės struktūra", "Checked database schema update for apps" : "Tikrinama duomenų bazės struktūra įskiepiams", diff --git a/core/l10n/nds.js b/core/l10n/nds.js index ed29474b797..2051b30361a 100644 --- a/core/l10n/nds.js +++ b/core/l10n/nds.js @@ -104,7 +104,11 @@ OC.L10N.register( "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Dein Webserver ist für die Dateisynchronisierung noch nicht ordentlich eingerichtet, da die WebDAV-Schnittstelle fehlerhaft scheint. ", "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." : "Dieser Server ist nicht mit dem Internet verbunden. Das bedeutet, dass manche Funktionen, wie das Einbinden von externen Speichern, Benachrichtigungen über Aktualisierungen oder die Installation von Drittanbieter Apps nicht zur Verfügung stehen. Auch der Fernzugriff auf Dateien und das Senden von Hinweis-E-Mails könnte nicht funktionieren. Wir empfehlen die Internetverbindung dieses Servers zu aktivieren, wenn Du diese Funktionen nutzen möchtest.", "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." : "Der Zugriff auf Dein Datenverzeichnis und Deine Dateien ist über das Internet vermutlich möglich. Die .htaccess-Datei greift nicht. Wir empfehlen dringend den Webserver derart zu konfigurieren, dass das Datenverzeichnis nicht mehr zugreifbar ist oder das Datenverzeichnis nach außerhalb des Dokumentenwurzelverzeichnisses des Webservers zu verschieben.", + "Error" : "Fehler", "Password" : "Passwort", + "Send" : "Senden", + "can share" : "kann teilen", + "can edit" : "kann editieren", "Share" : "Teilen", "Delete" : "Löschen", "Personal" : "Persönlich", diff --git a/core/l10n/nds.json b/core/l10n/nds.json index bc8f8d2510c..cb2f908da76 100644 --- a/core/l10n/nds.json +++ b/core/l10n/nds.json @@ -102,7 +102,11 @@ "Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Dein Webserver ist für die Dateisynchronisierung noch nicht ordentlich eingerichtet, da die WebDAV-Schnittstelle fehlerhaft scheint. ", "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." : "Dieser Server ist nicht mit dem Internet verbunden. Das bedeutet, dass manche Funktionen, wie das Einbinden von externen Speichern, Benachrichtigungen über Aktualisierungen oder die Installation von Drittanbieter Apps nicht zur Verfügung stehen. Auch der Fernzugriff auf Dateien und das Senden von Hinweis-E-Mails könnte nicht funktionieren. Wir empfehlen die Internetverbindung dieses Servers zu aktivieren, wenn Du diese Funktionen nutzen möchtest.", "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." : "Der Zugriff auf Dein Datenverzeichnis und Deine Dateien ist über das Internet vermutlich möglich. Die .htaccess-Datei greift nicht. Wir empfehlen dringend den Webserver derart zu konfigurieren, dass das Datenverzeichnis nicht mehr zugreifbar ist oder das Datenverzeichnis nach außerhalb des Dokumentenwurzelverzeichnisses des Webservers zu verschieben.", + "Error" : "Fehler", "Password" : "Passwort", + "Send" : "Senden", + "can share" : "kann teilen", + "can edit" : "kann editieren", "Share" : "Teilen", "Delete" : "Löschen", "Personal" : "Persönlich", diff --git a/lib/l10n/es.js b/lib/l10n/es.js index 3eb2e71a7d4..9ee1f96f034 100644 --- a/lib/l10n/es.js +++ b/lib/l10n/es.js @@ -87,6 +87,7 @@ OC.L10N.register( "Sharing %s failed, because the backend does not allow shares from type %i" : "No se pudo compartir %s porque el repositorio no permite recursos compartidos del tipo %i", "Sharing %s failed, because the file does not exist" : "No se pudo compartir %s porque el archivo no existe", "You are not allowed to share %s" : "Usted no está autorizado para compartir %s", + "Sharing %s failed, because you can not share with yourself" : "Se falló al compartir %s, porque no puedes compartir contigo mismo", "Sharing %s failed, because the user %s does not exist" : "Se ha fallado al compartir %s, ya que el usuario %s no existe", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Se ha fallado al compartir %s, ya que el usuario %s no es miembro de ningún grupo del que %s sea miembro", "Sharing %s failed, because this item is already shared with %s" : "Se falló al compartir %s, ya que este elemento ya está compartido con %s", @@ -105,6 +106,7 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El motor compartido %s debe implementar la interfaz OCP\\Share_Backend", "Sharing backend %s not found" : "El motor compartido %s no se ha encontrado", "Sharing backend for %s not found" : "Motor compartido para %s no encontrado", + "Sharing failed, because the user %s is the original sharer" : "Se ha fallado al compartir, ya que el usuario %s es el compartidor original", "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Se ha fallado al compartir %s, ya que los permisos superan los permisos otorgados a %s", "Sharing %s failed, because resharing is not allowed" : "Se ha fallado al compartir %s, ya que volver a compartir no está permitido", "Sharing %s failed, because the sharing backend for %s could not find its source" : "Se ha fallado al compartir %s porque el motor compartido para %s podría no encontrar su origen", diff --git a/lib/l10n/es.json b/lib/l10n/es.json index bbc50f2b5b8..2d67df87024 100644 --- a/lib/l10n/es.json +++ b/lib/l10n/es.json @@ -85,6 +85,7 @@ "Sharing %s failed, because the backend does not allow shares from type %i" : "No se pudo compartir %s porque el repositorio no permite recursos compartidos del tipo %i", "Sharing %s failed, because the file does not exist" : "No se pudo compartir %s porque el archivo no existe", "You are not allowed to share %s" : "Usted no está autorizado para compartir %s", + "Sharing %s failed, because you can not share with yourself" : "Se falló al compartir %s, porque no puedes compartir contigo mismo", "Sharing %s failed, because the user %s does not exist" : "Se ha fallado al compartir %s, ya que el usuario %s no existe", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Se ha fallado al compartir %s, ya que el usuario %s no es miembro de ningún grupo del que %s sea miembro", "Sharing %s failed, because this item is already shared with %s" : "Se falló al compartir %s, ya que este elemento ya está compartido con %s", @@ -103,6 +104,7 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El motor compartido %s debe implementar la interfaz OCP\\Share_Backend", "Sharing backend %s not found" : "El motor compartido %s no se ha encontrado", "Sharing backend for %s not found" : "Motor compartido para %s no encontrado", + "Sharing failed, because the user %s is the original sharer" : "Se ha fallado al compartir, ya que el usuario %s es el compartidor original", "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Se ha fallado al compartir %s, ya que los permisos superan los permisos otorgados a %s", "Sharing %s failed, because resharing is not allowed" : "Se ha fallado al compartir %s, ya que volver a compartir no está permitido", "Sharing %s failed, because the sharing backend for %s could not find its source" : "Se ha fallado al compartir %s porque el motor compartido para %s podría no encontrar su origen", diff --git a/lib/l10n/lt_LT.js b/lib/l10n/lt_LT.js index 27392c84d2c..c93903ff75e 100644 --- a/lib/l10n/lt_LT.js +++ b/lib/l10n/lt_LT.js @@ -1,6 +1,9 @@ OC.L10N.register( "lib", { + "Cannot write into \"config\" directory!" : "Negalima rašyti į \"config\" aplanką!", + "This can usually be fixed by giving the webserver write access to the config directory" : "Tai gali būti ištaisyta suteikiant web serveriui rašymo teises į config aplanką", + "PHP %s or higher is required." : "Reikalinga PHP %s arba aukštesnė.", "Help" : "Pagalba", "Personal" : "Asmeniniai", "Users" : "Vartotojai", @@ -17,6 +20,8 @@ OC.L10N.register( "_%n minute ago_::_%n minutes ago_" : ["prieš %n min.","Prieš % minutes","Prieš %n minučių"], "seconds ago" : "prieš sekundę", "web services under your control" : "jūsų valdomos web paslaugos", + "Empty filename is not allowed" : "Tuščias failo pavadinimas neleidžiamas", + "File name is a reserved word" : "Failo pavadinimas negalimas, žodis rezervuotas", "File name contains at least one invalid character" : "Failo vardas sudarytas iš neleistinų simbolių", "App directory already exists" : "Programos aplankas jau egzistuoja", "Can't create app folder. Please fix permissions. %s" : "Nepavyksta sukurti aplanko. Prašome pataisyti leidimus. %s", diff --git a/lib/l10n/lt_LT.json b/lib/l10n/lt_LT.json index 674939a7a0a..2784c3aefc1 100644 --- a/lib/l10n/lt_LT.json +++ b/lib/l10n/lt_LT.json @@ -1,4 +1,7 @@ { "translations": { + "Cannot write into \"config\" directory!" : "Negalima rašyti į \"config\" aplanką!", + "This can usually be fixed by giving the webserver write access to the config directory" : "Tai gali būti ištaisyta suteikiant web serveriui rašymo teises į config aplanką", + "PHP %s or higher is required." : "Reikalinga PHP %s arba aukštesnė.", "Help" : "Pagalba", "Personal" : "Asmeniniai", "Users" : "Vartotojai", @@ -15,6 +18,8 @@ "_%n minute ago_::_%n minutes ago_" : ["prieš %n min.","Prieš % minutes","Prieš %n minučių"], "seconds ago" : "prieš sekundę", "web services under your control" : "jūsų valdomos web paslaugos", + "Empty filename is not allowed" : "Tuščias failo pavadinimas neleidžiamas", + "File name is a reserved word" : "Failo pavadinimas negalimas, žodis rezervuotas", "File name contains at least one invalid character" : "Failo vardas sudarytas iš neleistinų simbolių", "App directory already exists" : "Programos aplankas jau egzistuoja", "Can't create app folder. Please fix permissions. %s" : "Nepavyksta sukurti aplanko. Prašome pataisyti leidimus. %s", diff --git a/settings/l10n/cs_CZ.js b/settings/l10n/cs_CZ.js index e1097fc485f..3e5d3867c65 100644 --- a/settings/l10n/cs_CZ.js +++ b/settings/l10n/cs_CZ.js @@ -192,6 +192,7 @@ OC.L10N.register( "More" : "Více", "Less" : "Méně", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Soubor logu je větší než 100 MB. Jeho stažení zabere nějaký čas!", + "What to log" : "Co se má logovat", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "Je použita databáze SQLite. Pro větší instalace doporučujeme přejít na robustnější databázi.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Obzvláště při používání klientské aplikace pro synchronizaci s desktopem není SQLite doporučeno.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Pro migraci na jinou databázi lze použít aplikaci pro příkazový řádek: 'occ db:convert-type', nebo nahlédněte do dokumentace ↗.", diff --git a/settings/l10n/cs_CZ.json b/settings/l10n/cs_CZ.json index 9e3b9a7b72c..42771f82ba2 100644 --- a/settings/l10n/cs_CZ.json +++ b/settings/l10n/cs_CZ.json @@ -190,6 +190,7 @@ "More" : "Více", "Less" : "Méně", "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Soubor logu je větší než 100 MB. Jeho stažení zabere nějaký čas!", + "What to log" : "Co se má logovat", "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "Je použita databáze SQLite. Pro větší instalace doporučujeme přejít na robustnější databázi.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "Obzvláště při používání klientské aplikace pro synchronizaci s desktopem není SQLite doporučeno.", "To migrate to another database use the command line tool: 'occ db:convert-type', or see the documentation ↗." : "Pro migraci na jinou databázi lze použít aplikaci pro příkazový řádek: 'occ db:convert-type', nebo nahlédněte do dokumentace ↗.", diff --git a/settings/l10n/lt_LT.js b/settings/l10n/lt_LT.js index b54d9cad1fc..c1ec5be2214 100644 --- a/settings/l10n/lt_LT.js +++ b/settings/l10n/lt_LT.js @@ -1,12 +1,21 @@ OC.L10N.register( "settings", { + "APCu" : "APCu", + "Redis" : "Redis", + "Security & setup warnings" : "Saugos ir diegimo perspėjimai", "Sharing" : "Dalijimasis", + "Server-side encryption" : "Šifravimas serveryje", "External Storage" : "Išorinės saugyklos", "Cron" : "Cron", + "Email server" : "Pašto serveris", "Log" : "Žurnalas", + "Tips & tricks" : "Patarimai ir gudrybės", "Updates" : "Atnaujinimai", "Authentication error" : "Autentikacijos klaida", + "Your full name has been changed." : "Pilnas vardas pakeistas.", + "Unable to change full name" : "Nepavyko pakeisti pilno vardo", + "Couldn't remove app." : "Nepavyko pašalinti programėlės.", "Language changed" : "Kalba pakeista", "Invalid request" : "Klaidinga užklausa", "Admins can't remove themself from the admin group" : "Administratoriai negali pašalinti savęs iš administratorių grupės", @@ -17,11 +26,16 @@ OC.L10N.register( "No user supplied" : "Nepateiktas naudotojas", "Please provide an admin recovery password, otherwise all user data will be lost" : "Prašome įvesti administratoriaus atkūrimo slaptažodį, kitaip visi naudotojo suomenys bus prarasti", "Wrong admin recovery password. Please check the password and try again." : "Netinkamas administratoriau atkūrimo slaptažodis. Prašome pasitikrinti ir bandyti vėl.", + "Backend doesn't support password change, but the user's encryption key was successfully updated." : "Vartotojo slaptažodžio pakeitimas negalimas, bet šifravimo raktas atnaujintas sėkmingai.", "Unable to change password" : "Nepavyksta pakeisti slaptažodžio", "Enabled" : "Įjungta", + "Not enabled" : "Neįjungta", "Federated Cloud Sharing" : "Viešas dalijimasis padebesiu", "Saved" : "Išsaugoti", "Email sent" : "Laiškas išsiųstas", + "Invalid mail address" : "Neteisingas pašto adresas", + "Your %s account was created" : "Tavo paskyra %s sukurta", + "Unable to delete user." : "Nepavyko ištrinti vartotojo.", "Email saved" : "El. paštas išsaugotas", "All" : "Viskas", "Please wait...." : "Prašome palaukti...", diff --git a/settings/l10n/lt_LT.json b/settings/l10n/lt_LT.json index 6142e8a7158..cf389512098 100644 --- a/settings/l10n/lt_LT.json +++ b/settings/l10n/lt_LT.json @@ -1,10 +1,19 @@ { "translations": { + "APCu" : "APCu", + "Redis" : "Redis", + "Security & setup warnings" : "Saugos ir diegimo perspėjimai", "Sharing" : "Dalijimasis", + "Server-side encryption" : "Šifravimas serveryje", "External Storage" : "Išorinės saugyklos", "Cron" : "Cron", + "Email server" : "Pašto serveris", "Log" : "Žurnalas", + "Tips & tricks" : "Patarimai ir gudrybės", "Updates" : "Atnaujinimai", "Authentication error" : "Autentikacijos klaida", + "Your full name has been changed." : "Pilnas vardas pakeistas.", + "Unable to change full name" : "Nepavyko pakeisti pilno vardo", + "Couldn't remove app." : "Nepavyko pašalinti programėlės.", "Language changed" : "Kalba pakeista", "Invalid request" : "Klaidinga užklausa", "Admins can't remove themself from the admin group" : "Administratoriai negali pašalinti savęs iš administratorių grupės", @@ -15,11 +24,16 @@ "No user supplied" : "Nepateiktas naudotojas", "Please provide an admin recovery password, otherwise all user data will be lost" : "Prašome įvesti administratoriaus atkūrimo slaptažodį, kitaip visi naudotojo suomenys bus prarasti", "Wrong admin recovery password. Please check the password and try again." : "Netinkamas administratoriau atkūrimo slaptažodis. Prašome pasitikrinti ir bandyti vėl.", + "Backend doesn't support password change, but the user's encryption key was successfully updated." : "Vartotojo slaptažodžio pakeitimas negalimas, bet šifravimo raktas atnaujintas sėkmingai.", "Unable to change password" : "Nepavyksta pakeisti slaptažodžio", "Enabled" : "Įjungta", + "Not enabled" : "Neįjungta", "Federated Cloud Sharing" : "Viešas dalijimasis padebesiu", "Saved" : "Išsaugoti", "Email sent" : "Laiškas išsiųstas", + "Invalid mail address" : "Neteisingas pašto adresas", + "Your %s account was created" : "Tavo paskyra %s sukurta", + "Unable to delete user." : "Nepavyko ištrinti vartotojo.", "Email saved" : "El. paštas išsaugotas", "All" : "Viskas", "Please wait...." : "Prašome palaukti...", -- GitLab From fb3d5c7856b9fbed926091e91ec54de023859df8 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 2 Nov 2015 13:19:30 +0100 Subject: [PATCH 123/344] Add evert's davclient.js + es6-promise + IE8 workaround - Add davclient.js lib - Add es6-promise required by that lib - Wrote IE8 workaround lib/shim for davclient.js --- bower.json | 4 +- core/js/core.json | 8 +- core/js/files/ie8davclient.js | 169 ++++ core/vendor/.gitignore | 11 + core/vendor/davclient.js/LICENSE | 27 + core/vendor/davclient.js/lib/client.js | 296 ++++++ core/vendor/es6-promise/.bower.json | 40 + core/vendor/es6-promise/.npmignore | 11 + core/vendor/es6-promise/.release.json | 17 + core/vendor/es6-promise/.spmignore | 11 + core/vendor/es6-promise/LICENSE | 19 + core/vendor/es6-promise/dist/es6-promise.js | 972 ++++++++++++++++++++ lib/private/template.php | 11 +- 13 files changed, 1591 insertions(+), 5 deletions(-) create mode 100644 core/js/files/ie8davclient.js create mode 100644 core/vendor/davclient.js/LICENSE create mode 100644 core/vendor/davclient.js/lib/client.js create mode 100644 core/vendor/es6-promise/.bower.json create mode 100644 core/vendor/es6-promise/.npmignore create mode 100644 core/vendor/es6-promise/.release.json create mode 100644 core/vendor/es6-promise/.spmignore create mode 100644 core/vendor/es6-promise/LICENSE create mode 100644 core/vendor/es6-promise/dist/es6-promise.js diff --git a/bower.json b/bower.json index e8bb9a35f32..77d7d75e85c 100644 --- a/bower.json +++ b/bower.json @@ -27,6 +27,8 @@ "strengthify": "0.4.2", "underscore": "~1.8.0", "bootstrap": "~3.3.5", - "backbone": "~1.2.1" + "backbone": "~1.2.1", + "davclient.js": "https://github.com/evert/davclient.js.git", + "es6-promise": "https://github.com/jakearchibald/es6-promise.git#~2.3.0" } } diff --git a/core/js/core.json b/core/js/core.json index a80636e8463..c7621a08d62 100644 --- a/core/js/core.json +++ b/core/js/core.json @@ -8,7 +8,9 @@ "handlebars/handlebars.js", "blueimp-md5/js/md5.js", "bootstrap/js/tooltip.js", - "backbone/backbone.js" + "backbone/backbone.js", + "es6-promise/dist/es6-promise.js", + "davclient.js/lib/client.js" ], "libraries": [ "jquery-showpassword.js", @@ -39,6 +41,8 @@ "setupchecks.js", "../search/js/search.js", "mimetype.js", - "mimetypelist.js" + "mimetypelist.js", + "files/fileinfo.js", + "files/client.js" ] } diff --git a/core/js/files/ie8davclient.js b/core/js/files/ie8davclient.js new file mode 100644 index 00000000000..9887d34e5b4 --- /dev/null +++ b/core/js/files/ie8davclient.js @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global dav */ +(function(dav) { + + /** + * Override davclient.js methods with IE8-compatible logic + */ + dav.Client.prototype = _.extend({}, dav.Client.prototype, { + + /** + * Generates a propFind request. + * + * @param {string} url Url to do the propfind request on + * @param {Array} properties List of properties to retrieve. + * @return {Promise} + */ + propFind : function(url, properties, depth) { + + if(typeof depth == "undefined") { + depth = 0; + } + + var headers = { + Depth : depth, + 'Content-Type' : 'application/xml; charset=utf-8' + }; + + var body = + '\n' + + '\n'; + + for(var ii in properties) { + var propText = properties[ii]; + if (typeof propText !== 'string') { + // can happen on IE8 + continue; + } + var property = this.parseClarkNotation(properties[ii]); + if (this.xmlNamespaces[property.namespace]) { + body+=' <' + this.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n'; + } else { + body+=' \n'; + } + + } + body+=' \n'; + body+=''; + + return this.request('PROPFIND', url, headers, body).then( + function(result) { + var elements = this.parseMultiStatus(result.xhr.responseXML); + var response; + if (depth===0) { + response = { + status: result.status, + body: elements[0] + }; + } else { + response = { + status: result.status, + body: elements + }; + } + return response; + + }.bind(this) + ); + + }, + + + _getElementsByTagName: function(node, name, resolver) { + var parts = name.split(':'); + var tagName = parts[1]; + var namespace = resolver(parts[0]); + if (node.getElementsByTagNameNS) { + return node.getElementsByTagNameNS(namespace, tagName); + } + return node.getElementsByTagName(name); + }, + + /** + * Parses a multi-status response body. + * + * @param {string} xmlBody + * @param {Array} + */ + parseMultiStatus : function(doc) { + + var result = []; + var resolver = function(foo) { + var ii; + for(ii in this.xmlNamespaces) { + if (this.xmlNamespaces[ii] === foo) { + return ii; + } + } + }.bind(this); + + var responses = this._getElementsByTagName(doc, 'd:response', resolver); + var i; + for (i = 0; i < responses.length; i++) { + var responseNode = responses[i]; + var response = { + href : null, + propStat : [] + }; + + var hrefNode = this._getElementsByTagName(responseNode, 'd:href', resolver)[0]; + + response.href = hrefNode.textContent || hrefNode.text; + + var propStatNodes = this._getElementsByTagName(responseNode, 'd:propstat', resolver); + var j = 0; + + for (j = 0; j < propStatNodes.length; j++) { + var propStatNode = propStatNodes[j]; + var statusNode = this._getElementsByTagName(propStatNode, 'd:status', resolver)[0]; + + var propStat = { + status : statusNode.textContent || statusNode.text, + properties : [] + }; + + var propNode = this._getElementsByTagName(propStatNode, 'd:prop', resolver)[0]; + if (!propNode) { + continue; + } + var k = 0; + for (k = 0; k < propNode.childNodes.length; k++) { + var prop = propNode.childNodes[k]; + var value = prop.textContent || prop.text; + if (prop.childNodes && prop.childNodes.length > 0 && prop.childNodes[0].nodeType === 1) { + value = prop.childNodes; + } + propStat.properties['{' + prop.namespaceURI + '}' + (prop.localName || prop.baseName)] = value; + + } + response.propStat.push(propStat); + } + + result.push(response); + } + + return result; + + } + + + }); + +})(dav); + diff --git a/core/vendor/.gitignore b/core/vendor/.gitignore index bcbb59b6f24..09b6a47c72d 100644 --- a/core/vendor/.gitignore +++ b/core/vendor/.gitignore @@ -122,3 +122,14 @@ bootstrap/js/* # backbone backbone/backbone-min* + +# davclient.js +davclient.js/** +!davclient.js/lib/* +!davclient.js/LICENSE + +# es6-promise +es6-promise/** +!es6-promise/LICENSE +!es6-promise/dist/es6-promise.js + diff --git a/core/vendor/davclient.js/LICENSE b/core/vendor/davclient.js/LICENSE new file mode 100644 index 00000000000..fd7293e8f32 --- /dev/null +++ b/core/vendor/davclient.js/LICENSE @@ -0,0 +1,27 @@ +Copyright (C) 2013-2014 fruux GmbH (https://fruux.com/) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name Sabre nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. diff --git a/core/vendor/davclient.js/lib/client.js b/core/vendor/davclient.js/lib/client.js new file mode 100644 index 00000000000..93678f09248 --- /dev/null +++ b/core/vendor/davclient.js/lib/client.js @@ -0,0 +1,296 @@ +if (typeof dav == 'undefined') { dav = {}; }; + +dav.Client = function(options) { + var i; + for(i in options) { + this[i] = options[i]; + } + +}; + +dav.Client.prototype = { + + baseUrl : null, + + userName : null, + + password : null, + + + xmlNamespaces : { + 'DAV:' : 'd' + }, + + /** + * Generates a propFind request. + * + * @param {string} url Url to do the propfind request on + * @param {Array} properties List of properties to retrieve. + * @return {Promise} + */ + propFind : function(url, properties, depth) { + + if(typeof depth == "undefined") { + depth = 0; + } + + var headers = { + Depth : depth, + 'Content-Type' : 'application/xml; charset=utf-8' + }; + + var body = + '\n' + + '\n'; + + for(var ii in properties) { + + var property = this.parseClarkNotation(properties[ii]); + if (this.xmlNamespaces[property.namespace]) { + body+=' <' + this.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n'; + } else { + body+=' \n'; + } + + } + body+=' \n'; + body+=''; + + return this.request('PROPFIND', url, headers, body).then( + function(result) { + + var resultBody = this.parseMultiStatus(result.body); + if (depth===0) { + return { + status: result.status, + body: resultBody[0], + xhr: result.xhr + }; + } else { + return { + status: result.status, + body: resultBody, + xhr: result.xhr + }; + } + + }.bind(this) + ); + + }, + + /** + * Performs a HTTP request, and returns a Promise + * + * @param {string} method HTTP method + * @param {string} url Relative or absolute url + * @param {Object} headers HTTP headers as an object. + * @param {string} body HTTP request body. + * @return {Promise} + */ + request : function(method, url, headers, body) { + + var xhr = this.xhrProvider(); + + if (this.userName) { + headers['Authorization'] = 'Basic ' + btoa(this.userName + ':' + this.password); + // xhr.open(method, this.resolveUrl(url), true, this.userName, this.password); + } + xhr.open(method, this.resolveUrl(url), true); + var ii; + for(ii in headers) { + xhr.setRequestHeader(ii, headers[ii]); + } + xhr.send(body); + + return new Promise(function(fulfill, reject) { + + xhr.onreadystatechange = function() { + + if (xhr.readyState !== 4) { + return; + } + + fulfill({ + body: xhr.response, + status: xhr.status, + xhr: xhr + }); + + }; + + xhr.ontimeout = function() { + + reject(new Error('Timeout exceeded')); + + }; + + }); + + }, + + /** + * Returns an XMLHttpRequest object. + * + * This is in its own method, so it can be easily overridden. + * + * @return {XMLHttpRequest} + */ + xhrProvider : function() { + + return new XMLHttpRequest(); + + }, + + + /** + * Parses a multi-status response body. + * + * @param {string} xmlBody + * @param {Array} + */ + parseMultiStatus : function(xmlBody) { + + var parser = new DOMParser(); + var doc = parser.parseFromString(xmlBody, "application/xml"); + + var resolver = function(foo) { + var ii; + for(ii in this.xmlNamespaces) { + if (this.xmlNamespaces[ii] === foo) { + return ii; + } + } + }.bind(this); + + var responseIterator = doc.evaluate('/d:multistatus/d:response', doc, resolver); + + var result = []; + var responseNode = responseIterator.iterateNext(); + + while(responseNode) { + + var response = { + href : null, + propStat : [] + }; + + response.href = doc.evaluate('string(d:href)', responseNode, resolver).stringValue; + + var propStatIterator = doc.evaluate('d:propstat', responseNode, resolver); + var propStatNode = propStatIterator.iterateNext(); + + while(propStatNode) { + + var propStat = { + status : doc.evaluate('string(d:status)', propStatNode, resolver).stringValue, + properties : [], + }; + + var propIterator = doc.evaluate('d:prop/*', propStatNode, resolver); + + var propNode = propIterator.iterateNext(); + while(propNode) { + var content = propNode.textContent; + if (!content && propNode.hasChildNodes()) { + content = propNode.childNodes; + } + + propStat.properties['{' + propNode.namespaceURI + '}' + propNode.localName] = content; + propNode = propIterator.iterateNext(); + + } + response.propStat.push(propStat); + propStatNode = propStatIterator.iterateNext(); + + + } + + result.push(response); + responseNode = responseIterator.iterateNext(); + + } + + return result; + + }, + + /** + * Takes a relative url, and maps it to an absolute url, using the baseUrl + * + * @param {string} url + * @return {string} + */ + resolveUrl : function(url) { + + // Note: this is rudamentary.. not sure yet if it handles every case. + if (/^https?:\/\//i.test(url)) { + // absolute + return url; + } + + var baseParts = this.parseUrl(this.baseUrl); + if (url.charAt('/')) { + // Url starts with a slash + return baseParts.root + url; + } + + // Url does not start with a slash, we need grab the base url right up until the last slash. + var newUrl = baseParts.root + '/'; + if (baseParts.path.lastIndexOf('/')!==-1) { + newUrl = newUrl = baseParts.path.subString(0, baseParts.path.lastIndexOf('/')) + '/'; + } + newUrl+=url; + return url; + + }, + + /** + * Parses a url and returns its individual components. + * + * @param {String} url + * @return {Object} + */ + parseUrl : function(url) { + + var parts = url.match(/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/); + var result = { + url : parts[0], + scheme : parts[1], + host : parts[3], + port : parts[4], + path : parts[5], + query : parts[6], + fragment : parts[7], + }; + result.root = + result.scheme + '://' + + result.host + + (result.port ? ':' + result.port : ''); + + return result; + + }, + + parseClarkNotation : function(propertyName) { + + var result = propertyName.match(/^{([^}]+)}(.*)$/); + if (!result) { + return; + } + + return { + name : result[2], + namespace : result[1] + }; + + } + +}; + diff --git a/core/vendor/es6-promise/.bower.json b/core/vendor/es6-promise/.bower.json new file mode 100644 index 00000000000..f8c28b04e53 --- /dev/null +++ b/core/vendor/es6-promise/.bower.json @@ -0,0 +1,40 @@ +{ + "name": "es6-promise", + "namespace": "Promise", + "version": "2.3.0", + "description": "A polyfill for ES6-style Promises, tracking rsvp", + "authors": [ + "Stefan Penner " + ], + "main": "dist/es6-promise.js", + "keywords": [ + "promise" + ], + "repository": { + "type": "git", + "url": "git://github.com/jakearchibald/ES6-Promises.git" + }, + "bugs": { + "url": "https://github.com/jakearchibald/ES6-Promises/issues" + }, + "license": "MIT", + "ignore": [ + "node_modules", + "bower_components", + "test", + "tests", + "vendor", + "tasks" + ], + "homepage": "https://github.com/jakearchibald/es6-promise", + "_release": "2.3.0", + "_resolution": { + "type": "version", + "tag": "2.3.0", + "commit": "fcbab11a1a981eb2290bfff89017cb764335a2a5" + }, + "_source": "https://github.com/jakearchibald/es6-promise.git", + "_target": "~2.3.0", + "_originalSource": "https://github.com/jakearchibald/es6-promise.git", + "_direct": true +} \ No newline at end of file diff --git a/core/vendor/es6-promise/.npmignore b/core/vendor/es6-promise/.npmignore new file mode 100644 index 00000000000..7a758111e9e --- /dev/null +++ b/core/vendor/es6-promise/.npmignore @@ -0,0 +1,11 @@ +/node_modules/ +/tmp +/tasks +/test +/vendor +/.jshintrc +/.npmignore +/.travis.yml +/Gruntfile.js +/component.json +/index.html diff --git a/core/vendor/es6-promise/.release.json b/core/vendor/es6-promise/.release.json new file mode 100644 index 00000000000..dee8cbc5d92 --- /dev/null +++ b/core/vendor/es6-promise/.release.json @@ -0,0 +1,17 @@ +{ + "non-interactive": true, + "dry-run": false, + "verbose": false, + "force": false, + "pkgFiles": ["package.json", "bower.json"], + "increment": "patch", + "commitMessage": "Release %s", + "tagName": "%s", + "tagAnnotation": "Release %s", + "buildCommand": "npm run-script build-all", + "distRepo": "git@github.com:components/rsvp.js.git", + "distStageDir": "tmp/stage", + "distBase": "dist", + "distFiles": ["**/*", "../package.json", "../bower.json"], + "publish": false +} diff --git a/core/vendor/es6-promise/.spmignore b/core/vendor/es6-promise/.spmignore new file mode 100644 index 00000000000..7a758111e9e --- /dev/null +++ b/core/vendor/es6-promise/.spmignore @@ -0,0 +1,11 @@ +/node_modules/ +/tmp +/tasks +/test +/vendor +/.jshintrc +/.npmignore +/.travis.yml +/Gruntfile.js +/component.json +/index.html diff --git a/core/vendor/es6-promise/LICENSE b/core/vendor/es6-promise/LICENSE new file mode 100644 index 00000000000..954ec5992df --- /dev/null +++ b/core/vendor/es6-promise/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/core/vendor/es6-promise/dist/es6-promise.js b/core/vendor/es6-promise/dist/es6-promise.js new file mode 100644 index 00000000000..aff0482ee5e --- /dev/null +++ b/core/vendor/es6-promise/dist/es6-promise.js @@ -0,0 +1,972 @@ +/*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE + * @version 2.3.0 + */ + +(function() { + "use strict"; + function lib$es6$promise$utils$$objectOrFunction(x) { + return typeof x === 'function' || (typeof x === 'object' && x !== null); + } + + function lib$es6$promise$utils$$isFunction(x) { + return typeof x === 'function'; + } + + function lib$es6$promise$utils$$isMaybeThenable(x) { + return typeof x === 'object' && x !== null; + } + + var lib$es6$promise$utils$$_isArray; + if (!Array.isArray) { + lib$es6$promise$utils$$_isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; + } else { + lib$es6$promise$utils$$_isArray = Array.isArray; + } + + var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray; + var lib$es6$promise$asap$$len = 0; + var lib$es6$promise$asap$$toString = {}.toString; + var lib$es6$promise$asap$$vertxNext; + var lib$es6$promise$asap$$customSchedulerFn; + + var lib$es6$promise$asap$$asap = function asap(callback, arg) { + lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback; + lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg; + lib$es6$promise$asap$$len += 2; + if (lib$es6$promise$asap$$len === 2) { + // If len is 2, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + if (lib$es6$promise$asap$$customSchedulerFn) { + lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush); + } else { + lib$es6$promise$asap$$scheduleFlush(); + } + } + } + + function lib$es6$promise$asap$$setScheduler(scheduleFn) { + lib$es6$promise$asap$$customSchedulerFn = scheduleFn; + } + + function lib$es6$promise$asap$$setAsap(asapFn) { + lib$es6$promise$asap$$asap = asapFn; + } + + var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined; + var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {}; + var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver; + var lib$es6$promise$asap$$isNode = typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; + + // test for web worker but not in IE10 + var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && + typeof importScripts !== 'undefined' && + typeof MessageChannel !== 'undefined'; + + // node + function lib$es6$promise$asap$$useNextTick() { + var nextTick = process.nextTick; + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // setImmediate should be used instead instead + var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/); + if (Array.isArray(version) && version[1] === '0' && version[2] === '10') { + nextTick = setImmediate; + } + return function() { + nextTick(lib$es6$promise$asap$$flush); + }; + } + + // vertx + function lib$es6$promise$asap$$useVertxTimer() { + return function() { + lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush); + }; + } + + function lib$es6$promise$asap$$useMutationObserver() { + var iterations = 0; + var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + + return function() { + node.data = (iterations = ++iterations % 2); + }; + } + + // web worker + function lib$es6$promise$asap$$useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = lib$es6$promise$asap$$flush; + return function () { + channel.port2.postMessage(0); + }; + } + + function lib$es6$promise$asap$$useSetTimeout() { + return function() { + setTimeout(lib$es6$promise$asap$$flush, 1); + }; + } + + var lib$es6$promise$asap$$queue = new Array(1000); + function lib$es6$promise$asap$$flush() { + for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) { + var callback = lib$es6$promise$asap$$queue[i]; + var arg = lib$es6$promise$asap$$queue[i+1]; + + callback(arg); + + lib$es6$promise$asap$$queue[i] = undefined; + lib$es6$promise$asap$$queue[i+1] = undefined; + } + + lib$es6$promise$asap$$len = 0; + } + + function lib$es6$promise$asap$$attemptVertex() { + try { + var r = require; + var vertx = r('vertx'); + lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext; + return lib$es6$promise$asap$$useVertxTimer(); + } catch(e) { + return lib$es6$promise$asap$$useSetTimeout(); + } + } + + var lib$es6$promise$asap$$scheduleFlush; + // Decide what async method to use to triggering processing of queued callbacks: + if (lib$es6$promise$asap$$isNode) { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick(); + } else if (lib$es6$promise$asap$$BrowserMutationObserver) { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver(); + } else if (lib$es6$promise$asap$$isWorker) { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel(); + } else if (lib$es6$promise$asap$$browserWindow === undefined && typeof require === 'function') { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertex(); + } else { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout(); + } + + function lib$es6$promise$$internal$$noop() {} + + var lib$es6$promise$$internal$$PENDING = void 0; + var lib$es6$promise$$internal$$FULFILLED = 1; + var lib$es6$promise$$internal$$REJECTED = 2; + + var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject(); + + function lib$es6$promise$$internal$$selfFullfillment() { + return new TypeError("You cannot resolve a promise with itself"); + } + + function lib$es6$promise$$internal$$cannotReturnOwn() { + return new TypeError('A promises callback cannot return that same promise.'); + } + + function lib$es6$promise$$internal$$getThen(promise) { + try { + return promise.then; + } catch(error) { + lib$es6$promise$$internal$$GET_THEN_ERROR.error = error; + return lib$es6$promise$$internal$$GET_THEN_ERROR; + } + } + + function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { + try { + then.call(value, fulfillmentHandler, rejectionHandler); + } catch(e) { + return e; + } + } + + function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) { + lib$es6$promise$asap$$asap(function(promise) { + var sealed = false; + var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) { + if (sealed) { return; } + sealed = true; + if (thenable !== value) { + lib$es6$promise$$internal$$resolve(promise, value); + } else { + lib$es6$promise$$internal$$fulfill(promise, value); + } + }, function(reason) { + if (sealed) { return; } + sealed = true; + + lib$es6$promise$$internal$$reject(promise, reason); + }, 'Settle: ' + (promise._label || ' unknown promise')); + + if (!sealed && error) { + sealed = true; + lib$es6$promise$$internal$$reject(promise, error); + } + }, promise); + } + + function lib$es6$promise$$internal$$handleOwnThenable(promise, thenable) { + if (thenable._state === lib$es6$promise$$internal$$FULFILLED) { + lib$es6$promise$$internal$$fulfill(promise, thenable._result); + } else if (thenable._state === lib$es6$promise$$internal$$REJECTED) { + lib$es6$promise$$internal$$reject(promise, thenable._result); + } else { + lib$es6$promise$$internal$$subscribe(thenable, undefined, function(value) { + lib$es6$promise$$internal$$resolve(promise, value); + }, function(reason) { + lib$es6$promise$$internal$$reject(promise, reason); + }); + } + } + + function lib$es6$promise$$internal$$handleMaybeThenable(promise, maybeThenable) { + if (maybeThenable.constructor === promise.constructor) { + lib$es6$promise$$internal$$handleOwnThenable(promise, maybeThenable); + } else { + var then = lib$es6$promise$$internal$$getThen(maybeThenable); + + if (then === lib$es6$promise$$internal$$GET_THEN_ERROR) { + lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$GET_THEN_ERROR.error); + } else if (then === undefined) { + lib$es6$promise$$internal$$fulfill(promise, maybeThenable); + } else if (lib$es6$promise$utils$$isFunction(then)) { + lib$es6$promise$$internal$$handleForeignThenable(promise, maybeThenable, then); + } else { + lib$es6$promise$$internal$$fulfill(promise, maybeThenable); + } + } + } + + function lib$es6$promise$$internal$$resolve(promise, value) { + if (promise === value) { + lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFullfillment()); + } else if (lib$es6$promise$utils$$objectOrFunction(value)) { + lib$es6$promise$$internal$$handleMaybeThenable(promise, value); + } else { + lib$es6$promise$$internal$$fulfill(promise, value); + } + } + + function lib$es6$promise$$internal$$publishRejection(promise) { + if (promise._onerror) { + promise._onerror(promise._result); + } + + lib$es6$promise$$internal$$publish(promise); + } + + function lib$es6$promise$$internal$$fulfill(promise, value) { + if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; } + + promise._result = value; + promise._state = lib$es6$promise$$internal$$FULFILLED; + + if (promise._subscribers.length !== 0) { + lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise); + } + } + + function lib$es6$promise$$internal$$reject(promise, reason) { + if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; } + promise._state = lib$es6$promise$$internal$$REJECTED; + promise._result = reason; + + lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise); + } + + function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) { + var subscribers = parent._subscribers; + var length = subscribers.length; + + parent._onerror = null; + + subscribers[length] = child; + subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment; + subscribers[length + lib$es6$promise$$internal$$REJECTED] = onRejection; + + if (length === 0 && parent._state) { + lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent); + } + } + + function lib$es6$promise$$internal$$publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; + + if (subscribers.length === 0) { return; } + + var child, callback, detail = promise._result; + + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + + if (child) { + lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } + + promise._subscribers.length = 0; + } + + function lib$es6$promise$$internal$$ErrorObject() { + this.error = null; + } + + var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject(); + + function lib$es6$promise$$internal$$tryCatch(callback, detail) { + try { + return callback(detail); + } catch(e) { + lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e; + return lib$es6$promise$$internal$$TRY_CATCH_ERROR; + } + } + + function lib$es6$promise$$internal$$invokeCallback(settled, promise, callback, detail) { + var hasCallback = lib$es6$promise$utils$$isFunction(callback), + value, error, succeeded, failed; + + if (hasCallback) { + value = lib$es6$promise$$internal$$tryCatch(callback, detail); + + if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value = null; + } else { + succeeded = true; + } + + if (promise === value) { + lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn()); + return; + } + + } else { + value = detail; + succeeded = true; + } + + if (promise._state !== lib$es6$promise$$internal$$PENDING) { + // noop + } else if (hasCallback && succeeded) { + lib$es6$promise$$internal$$resolve(promise, value); + } else if (failed) { + lib$es6$promise$$internal$$reject(promise, error); + } else if (settled === lib$es6$promise$$internal$$FULFILLED) { + lib$es6$promise$$internal$$fulfill(promise, value); + } else if (settled === lib$es6$promise$$internal$$REJECTED) { + lib$es6$promise$$internal$$reject(promise, value); + } + } + + function lib$es6$promise$$internal$$initializePromise(promise, resolver) { + try { + resolver(function resolvePromise(value){ + lib$es6$promise$$internal$$resolve(promise, value); + }, function rejectPromise(reason) { + lib$es6$promise$$internal$$reject(promise, reason); + }); + } catch(e) { + lib$es6$promise$$internal$$reject(promise, e); + } + } + + function lib$es6$promise$enumerator$$Enumerator(Constructor, input) { + var enumerator = this; + + enumerator._instanceConstructor = Constructor; + enumerator.promise = new Constructor(lib$es6$promise$$internal$$noop); + + if (enumerator._validateInput(input)) { + enumerator._input = input; + enumerator.length = input.length; + enumerator._remaining = input.length; + + enumerator._init(); + + if (enumerator.length === 0) { + lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result); + } else { + enumerator.length = enumerator.length || 0; + enumerator._enumerate(); + if (enumerator._remaining === 0) { + lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result); + } + } + } else { + lib$es6$promise$$internal$$reject(enumerator.promise, enumerator._validationError()); + } + } + + lib$es6$promise$enumerator$$Enumerator.prototype._validateInput = function(input) { + return lib$es6$promise$utils$$isArray(input); + }; + + lib$es6$promise$enumerator$$Enumerator.prototype._validationError = function() { + return new Error('Array Methods must be provided an Array'); + }; + + lib$es6$promise$enumerator$$Enumerator.prototype._init = function() { + this._result = new Array(this.length); + }; + + var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator; + + lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() { + var enumerator = this; + + var length = enumerator.length; + var promise = enumerator.promise; + var input = enumerator._input; + + for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) { + enumerator._eachEntry(input[i], i); + } + }; + + lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { + var enumerator = this; + var c = enumerator._instanceConstructor; + + if (lib$es6$promise$utils$$isMaybeThenable(entry)) { + if (entry.constructor === c && entry._state !== lib$es6$promise$$internal$$PENDING) { + entry._onerror = null; + enumerator._settledAt(entry._state, i, entry._result); + } else { + enumerator._willSettleAt(c.resolve(entry), i); + } + } else { + enumerator._remaining--; + enumerator._result[i] = entry; + } + }; + + lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { + var enumerator = this; + var promise = enumerator.promise; + + if (promise._state === lib$es6$promise$$internal$$PENDING) { + enumerator._remaining--; + + if (state === lib$es6$promise$$internal$$REJECTED) { + lib$es6$promise$$internal$$reject(promise, value); + } else { + enumerator._result[i] = value; + } + } + + if (enumerator._remaining === 0) { + lib$es6$promise$$internal$$fulfill(promise, enumerator._result); + } + }; + + lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { + var enumerator = this; + + lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) { + enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value); + }, function(reason) { + enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason); + }); + }; + function lib$es6$promise$promise$all$$all(entries) { + return new lib$es6$promise$enumerator$$default(this, entries).promise; + } + var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all; + function lib$es6$promise$promise$race$$race(entries) { + /*jshint validthis:true */ + var Constructor = this; + + var promise = new Constructor(lib$es6$promise$$internal$$noop); + + if (!lib$es6$promise$utils$$isArray(entries)) { + lib$es6$promise$$internal$$reject(promise, new TypeError('You must pass an array to race.')); + return promise; + } + + var length = entries.length; + + function onFulfillment(value) { + lib$es6$promise$$internal$$resolve(promise, value); + } + + function onRejection(reason) { + lib$es6$promise$$internal$$reject(promise, reason); + } + + for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) { + lib$es6$promise$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); + } + + return promise; + } + var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race; + function lib$es6$promise$promise$resolve$$resolve(object) { + /*jshint validthis:true */ + var Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + var promise = new Constructor(lib$es6$promise$$internal$$noop); + lib$es6$promise$$internal$$resolve(promise, object); + return promise; + } + var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve; + function lib$es6$promise$promise$reject$$reject(reason) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(lib$es6$promise$$internal$$noop); + lib$es6$promise$$internal$$reject(promise, reason); + return promise; + } + var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject; + + var lib$es6$promise$promise$$counter = 0; + + function lib$es6$promise$promise$$needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); + } + + function lib$es6$promise$promise$$needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); + } + + var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise; + /** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise's eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + var promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + var xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @param {function} resolver + Useful for tooling. + @constructor + */ + function lib$es6$promise$promise$$Promise(resolver) { + this._id = lib$es6$promise$promise$$counter++; + this._state = undefined; + this._result = undefined; + this._subscribers = []; + + if (lib$es6$promise$$internal$$noop !== resolver) { + if (!lib$es6$promise$utils$$isFunction(resolver)) { + lib$es6$promise$promise$$needsResolver(); + } + + if (!(this instanceof lib$es6$promise$promise$$Promise)) { + lib$es6$promise$promise$$needsNew(); + } + + lib$es6$promise$$internal$$initializePromise(this, resolver); + } + } + + lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default; + lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default; + lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default; + lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default; + lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler; + lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap; + lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap; + + lib$es6$promise$promise$$Promise.prototype = { + constructor: lib$es6$promise$promise$$Promise, + + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + + Chaining + -------- + + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we're unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + + Assimilation + ------------ + + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + + If the assimliated promise rejects, then the downstream promise will also reject. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + + Simple Example + -------------- + + Synchronous Example + + ```javascript + var result; + + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + + Promise Example; + + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + + Advanced Example + -------------- + + Synchronous Example + + ```javascript + var author, books; + + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + + function foundBooks(books) { + + } + + function failure(reason) { + + } + + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + + Promise Example; + + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + + @method then + @param {Function} onFulfilled + @param {Function} onRejected + Useful for tooling. + @return {Promise} + */ + then: function(onFulfillment, onRejection) { + var parent = this; + var state = parent._state; + + if (state === lib$es6$promise$$internal$$FULFILLED && !onFulfillment || state === lib$es6$promise$$internal$$REJECTED && !onRejection) { + return this; + } + + var child = new this.constructor(lib$es6$promise$$internal$$noop); + var result = parent._result; + + if (state) { + var callback = arguments[state - 1]; + lib$es6$promise$asap$$asap(function(){ + lib$es6$promise$$internal$$invokeCallback(state, child, callback, result); + }); + } else { + lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection); + } + + return child; + }, + + /** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + + ```js + function findAuthor(){ + throw new Error('couldn't find that author'); + } + + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + + @method catch + @param {Function} onRejection + Useful for tooling. + @return {Promise} + */ + 'catch': function(onRejection) { + return this.then(null, onRejection); + } + }; + function lib$es6$promise$polyfill$$polyfill() { + var local; + + if (typeof global !== 'undefined') { + local = global; + } else if (typeof self !== 'undefined') { + local = self; + } else { + try { + local = Function('return this')(); + } catch (e) { + throw new Error('polyfill failed because global object is unavailable in this environment'); + } + } + + var P = local.Promise; + + if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) { + return; + } + + local.Promise = lib$es6$promise$promise$$default; + } + var lib$es6$promise$polyfill$$default = lib$es6$promise$polyfill$$polyfill; + + var lib$es6$promise$umd$$ES6Promise = { + 'Promise': lib$es6$promise$promise$$default, + 'polyfill': lib$es6$promise$polyfill$$default + }; + + /* global define:true module:true window: true */ + if (typeof define === 'function' && define['amd']) { + define(function() { return lib$es6$promise$umd$$ES6Promise; }); + } else if (typeof module !== 'undefined' && module['exports']) { + module['exports'] = lib$es6$promise$umd$$ES6Promise; + } else if (typeof this !== 'undefined') { + this['ES6Promise'] = lib$es6$promise$umd$$ES6Promise; + } + + lib$es6$promise$polyfill$$default(); +}).call(this); + diff --git a/lib/private/template.php b/lib/private/template.php index 97666f0b8dc..2c9721dc964 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -143,7 +143,9 @@ class OC_Template extends \OC\Template\Base { OC_Util::addStyle("jquery.ocdialog"); OC_Util::addScript("compatibility", null, true); OC_Util::addScript("placeholders", null, true); - + OC_Util::addScript('files/fileinfo'); + OC_Util::addScript('files/client'); + // Add the stuff we need always // following logic will import all vendor libraries that are // specified in core/js/core.json @@ -158,7 +160,12 @@ class OC_Template extends \OC\Template\Base { } else { throw new \Exception('Cannot read core/js/core.json'); } - + + if (\OC::$server->getRequest()->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE_8])) { + // shim for the davclient.js library + \OCP\Util::addScript('files/ie8davclient'); + } + self::$initTemplateEngineFirstRun = false; } -- GitLab From f120846e291bf83244831770c5f25b730fa8ba90 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 13 Jul 2015 17:31:47 +0200 Subject: [PATCH 124/344] Added OC.Files.Client Webdav-based files client --- buildjsdocs.sh | 2 +- core/js/files/client.js | 673 ++++++++++++++++++++++ core/js/files/fileinfo.js | 143 +++++ core/js/js.js | 1 - core/js/tests/specHelper.js | 1 + core/js/tests/specs/files/clientSpec.js | 712 ++++++++++++++++++++++++ tests/karma.config.js | 6 +- 7 files changed, 1533 insertions(+), 5 deletions(-) create mode 100644 core/js/files/client.js create mode 100644 core/js/files/fileinfo.js create mode 100644 core/js/tests/specs/files/clientSpec.js diff --git a/buildjsdocs.sh b/buildjsdocs.sh index 90562558f66..57eefb29fd0 100755 --- a/buildjsdocs.sh +++ b/buildjsdocs.sh @@ -11,7 +11,7 @@ NPM="$(which npm 2>/dev/null)" PREFIX="build" OUTPUT_DIR="build/jsdocs" -JS_FILES="core/js/*.js apps/*/js/*.js" +JS_FILES="core/js/*.js core/js/**/*.js apps/*/js/*.js" if test -z "$NPM" then diff --git a/core/js/files/client.js b/core/js/files/client.js new file mode 100644 index 00000000000..9bb7bb999fd --- /dev/null +++ b/core/js/files/client.js @@ -0,0 +1,673 @@ +/* + * Copyright (c) 2015 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global dav */ + +(function(OC, FileInfo) { + /** + * @class OC.Files.Client + * @classdesc Client to access files on the server + * + * @param {Object} options + * @param {String} options.host host name + * @param {int} [options.port] port + * @param {boolean} [options.useHTTPS] whether to use https + * @param {String} [options.root] root path + * @param {String} [options.userName] user name + * @param {String} [options.password] password + * + * @since 8.2 + */ + var Client = function(options) { + this._root = options.root; + if (this._root.charAt(this._root.length - 1) === '/') { + this._root = this._root.substr(0, this._root.length - 1); + } + + if (!options.port) { + // workaround in case port is null or empty + options.port = undefined; + } + var url = ''; + var port = ''; + if (options.useHTTPS) { + url += 'https://'; + if (options.port && options.port !== 443) { + port = ':' + options.port; + } + } else { + url += 'http://'; + if (options.port && options.port !== 80) { + port = ':' + options.port; + } + } + var credentials = ''; + if (options.userName) { + credentials += encodeURIComponent(options.userName); + } + if (options.password) { + credentials += ':' + encodeURIComponent(options.password); + } + if (credentials.length > 0) { + url += credentials + '@'; + } + + url += options.host + port + this._root; + this._defaultHeaders = options.defaultHeaders || {'X-Requested-With': 'XMLHttpRequest'}; + this._baseUrl = url; + this._client = new dav.Client({ + baseUrl: this._baseUrl, + xmlNamespaces: { + 'DAV:': 'd', + 'http://owncloud.org/ns': 'oc' + } + }); + this._client.xhrProvider = _.bind(this._xhrProvider, this); + }; + + Client.NS_OWNCLOUD = 'http://owncloud.org/ns'; + Client.NS_DAV = 'DAV:'; + Client._PROPFIND_PROPERTIES = [ + /** + * Modified time + */ + [Client.NS_DAV, 'getlastmodified'], + /** + * Etag + */ + [Client.NS_DAV, 'getetag'], + /** + * Mime type + */ + [Client.NS_DAV, 'getcontenttype'], + /** + * Resource type "collection" for folders, empty otherwise + */ + [Client.NS_DAV, 'resourcetype'], + /** + * Compound file id, contains fileid + server instance id + */ + [Client.NS_OWNCLOUD, 'id'], + /** + * Letter-coded permissions + */ + [Client.NS_OWNCLOUD, 'permissions'], + //[Client.NS_OWNCLOUD, 'downloadURL'], + /** + * Folder sizes + */ + [Client.NS_OWNCLOUD, 'size'], + /** + * File sizes + */ + [Client.NS_DAV, 'getcontentlength'] + ]; + + /** + * @memberof OC.Files + */ + Client.prototype = { + + /** + * Root path of the Webdav endpoint + * + * @type string + */ + _root: null, + + /** + * Client from the library + * + * @type nl.sara.webdav.Client + */ + _client: null, + + /** + * Returns the configured XHR provider for davclient + * @return {XMLHttpRequest} + */ + _xhrProvider: function() { + var headers = this._defaultHeaders; + var xhr = new XMLHttpRequest(); + var oldOpen = xhr.open; + // override open() method to add headers + xhr.open = function() { + var result = oldOpen.apply(this, arguments); + _.each(headers, function(value, key) { + xhr.setRequestHeader(key, value); + }); + return result; + }; + return xhr; + }, + + /** + * Prepends the base url to the given path sections + * + * @param {...String} path sections + * + * @return {String} base url + joined path, any leading or trailing slash + * will be kept + */ + _buildUrl: function() { + var path = this._buildPath.apply(this, arguments); + if (path.charAt([path.length - 1]) === '/') { + path = path.substr(0, path.length - 1); + } + if (path.charAt(0) === '/') { + path = path.substr(1); + } + return this._baseUrl + '/' + path; + }, + + /** + * Append the path to the root and also encode path + * sections + * + * @param {...String} path sections + * + * @return {String} joined path, any leading or trailing slash + * will be kept + */ + _buildPath: function() { + var path = OC.joinPaths.apply(this, arguments); + var sections = path.split('/'); + var i; + for (i = 0; i < sections.length; i++) { + sections[i] = encodeURIComponent(sections[i]); + } + path = sections.join('/'); + return path; + }, + + /** + * Parse headers string into a map + * + * @param {string} headersString headers list as string + * + * @return {Object.} map of header name to header contents + */ + _parseHeaders: function(headersString) { + var headerRows = headersString.split('\n'); + var headers = {}; + for (var i = 0; i < headerRows.length; i++) { + var sepPos = headerRows[i].indexOf(':'); + if (sepPos < 0) { + continue; + } + + var headerName = headerRows[i].substr(0, sepPos); + var headerValue = headerRows[i].substr(sepPos + 2); + + if (!headers[headerName]) { + // make it an array + headers[headerName] = []; + } + + headers[headerName].push(headerValue); + } + return headers; + }, + + /** + * Parses the compound file id + * + * @param {string} compoundFileId compound file id as returned by the server + * + * @return {int} local file id, stripped of the instance id + */ + _parseFileId: function(compoundFileId) { + if (!compoundFileId || compoundFileId.length < 8) { + return null; + } + return parseInt(compoundFileId.substr(0, 8), 10); + }, + + /** + * Parses the etag response which is in double quotes. + * + * @param {string} etag etag value in double quotes + * + * @return {string} etag without double quotes + */ + _parseEtag: function(etag) { + if (etag.charAt(0) === '"') { + return etag.split('"')[1]; + } + return etag; + }, + + /** + * Parse Webdav result + * + * @param {Object} response XML object + * + * @return {Array.} array of file info + */ + _parseFileInfo: function(response) { + var path = response.href; + if (path.substr(0, this._root.length) === this._root) { + path = path.substr(this._root.length); + } + + if (path.charAt(path.length - 1) === '/') { + path = path.substr(0, path.length - 1); + } + + path = '/' + decodeURIComponent(path); + + if (response.propStat.length === 1 && response.propStat[0].status !== 200) { + return null; + } + + var props = response.propStat[0].properties; + + var data = { + id: this._parseFileId(props['{' + Client.NS_OWNCLOUD + '}id']), + path: OC.dirname(path) || '/', + name: OC.basename(path), + mtime: new Date(props['{' + Client.NS_DAV + '}getlastmodified']), + _props: props + }; + + var etagProp = props['{' + Client.NS_DAV + '}getetag']; + if (!_.isUndefined(etagProp)) { + data.etag = this._parseEtag(etagProp); + } + + var sizeProp = props['{' + Client.NS_DAV + '}getcontentlength']; + if (!_.isUndefined(sizeProp)) { + data.size = parseInt(sizeProp, 10); + } + + sizeProp = props['{' + Client.NS_OWNCLOUD + '}size']; + if (!_.isUndefined(sizeProp)) { + data.size = parseInt(sizeProp, 10); + } + + var contentType = props['{' + Client.NS_DAV + '}getcontenttype']; + if (!_.isUndefined(contentType)) { + data.mimetype = contentType; + } + + var resType = props['{' + Client.NS_DAV + '}resourcetype']; + var isFile = true; + if (!data.mimetype && resType) { + var xmlvalue = resType[0]; + if (xmlvalue.namespaceURI === Client.NS_DAV && xmlvalue.nodeName.split(':')[1] === 'collection') { + data.mimetype = 'httpd/unix-directory'; + isFile = false; + } + } + + data.permissions = OC.PERMISSION_READ; + var permissionProp = props['{' + Client.NS_OWNCLOUD + '}permissions']; + if (!_.isUndefined(permissionProp)) { + var permString = permissionProp || ''; + data.mountType = null; + for (var i = 0; i < permString.length; i++) { + var c = permString.charAt(i); + switch (c) { + // FIXME: twisted permissions + case 'C': + case 'K': + data.permissions |= OC.PERMISSION_CREATE; + if (!isFile) { + data.permissions |= OC.PERMISSION_UPDATE; + } + break; + case 'W': + if (isFile) { + // also add create permissions + data.permissions |= OC.PERMISSION_CREATE; + } + data.permissions |= OC.PERMISSION_UPDATE; + break; + case 'D': + data.permissions |= OC.PERMISSION_DELETE; + break; + case 'R': + data.permissions |= OC.PERMISSION_SHARE; + break; + case 'M': + if (!data.mountType) { + // TODO: how to identify external-root ? + data.mountType = 'external'; + } + break; + case 'S': + // TODO: how to identify shared-root ? + data.mountType = 'shared'; + break; + } + } + } + + return new FileInfo(data); + }, + + /** + * Parse Webdav multistatus + * + * @param {Array} responses + */ + _parseResult: function(responses) { + var self = this; + return _.map(responses, function(response) { + return self._parseFileInfo(response); + }); + }, + + /** + * Returns whether the given status code means success + * + * @param {int} status status code + * + * @return true if status code is between 200 and 299 included + */ + _isSuccessStatus: function(status) { + return status >= 200 && status <= 299; + }, + + /** + * Returns the default PROPFIND properties to use during a call. + * + * @return {Array.} array of properties + */ + _getPropfindProperties: function() { + if (!this._propfindProperties) { + this._propfindProperties = _.map(Client._PROPFIND_PROPERTIES, function(propDef) { + return '{' + propDef[0] + '}' + propDef[1]; + }); + } + return this._propfindProperties; + }, + + /** + * Lists the contents of a directory + * + * @param {String} path path to retrieve + * @param {Object} [options] options + * @param {boolean} [options.includeParent=false] set to true to keep + * the parent folder in the result list + * + * @return {Promise} promise + */ + getFolderContents: function(path, options) { + if (!path) { + path = ''; + } + var self = this; + var deferred = $.Deferred(); + var promise = deferred.promise(); + + // TODO: headers + this._client.propFind( + this._buildUrl(path), + this._getPropfindProperties(), + 1 + ).then(function(result) { + if (self._isSuccessStatus(result.status)) { + var results = self._parseResult(result.body); + if (!options || !options.includeParent) { + // remove root dir, the first entry + results.shift(); + } + deferred.resolve(result.status, results); + } else { + deferred.reject(result.status); + } + }); + return promise; + }, + + /** + * Returns the file info of a given path. + * + * @param {String} path path + * @param {Array} [properties] list of webdav properties to + * retrieve + * + * @return {Promise} promise + */ + getFileInfo: function(path) { + if (!path) { + path = ''; + } + var self = this; + var deferred = $.Deferred(); + var promise = deferred.promise(); + + // TODO: headers + this._client.propFind( + this._buildUrl(path), + this._getPropfindProperties(), + 0 + ).then( + function(result) { + if (self._isSuccessStatus(result.status)) { + deferred.resolve(result.status, self._parseResult([result.body])[0]); + } else { + deferred.reject(result.status); + } + } + ); + return promise; + }, + + /** + * Returns the contents of the given file. + * + * @param {String} path path to file + * + * @return {Promise} + */ + getFileContents: function(path) { + if (!path) { + throw 'Missing argument "path"'; + } + var self = this; + var deferred = $.Deferred(); + var promise = deferred.promise(); + + this._client.request( + 'GET', + this._buildUrl(path), + this._defaultHeaders + ).then( + function(result) { + if (self._isSuccessStatus(result.status)) { + deferred.resolve(result.status, result.body); + } else { + deferred.reject(result.status); + } + } + ); + return promise; + }, + + /** + * Puts the given data into the given file. + * + * @param {String} path path to file + * @param {String} body file body + * @param {Object} [options] + * @param {String} [options.contentType='text/plain'] content type + * @param {bool} [options.overwrite=true] whether to overwrite an existing file + * + * @return {Promise} + */ + putFileContents: function(path, body, options) { + if (!path) { + throw 'Missing argument "path"'; + } + var self = this; + var deferred = $.Deferred(); + var promise = deferred.promise(); + options = options || {}; + var headers = _.extend({}, this._defaultHeaders); + var contentType = 'text/plain'; + if (options.contentType) { + contentType = options.contentType; + } + + headers['Content-Type'] = contentType; + + if (_.isUndefined(options.overwrite) || options.overwrite) { + // will trigger 412 precondition failed if a file already exists + headers['If-None-Match'] = '*'; + } + + this._client.request( + 'PUT', + this._buildUrl(path), + headers, + body || '' + ).then( + function(result) { + if (self._isSuccessStatus(result.status)) { + deferred.resolve(result.status); + } else { + deferred.reject(result.status); + } + } + ); + return promise; + }, + + _simpleCall: function(method, path) { + if (!path) { + throw 'Missing argument "path"'; + } + + var self = this; + var deferred = $.Deferred(); + var promise = deferred.promise(); + + this._client.request( + method, + this._buildUrl(path), + this._defaultHeaders + ).then( + function(result) { + if (self._isSuccessStatus(result.status)) { + deferred.resolve(result.status); + } else { + deferred.reject(result.status); + } + } + ); + return promise; + }, + + /** + * Creates a directory + * + * @param {String} path path to create + * + * @return {Promise} + */ + createDirectory: function(path) { + return this._simpleCall('MKCOL', path); + }, + + /** + * Deletes a file or directory + * + * @param {String} path path to delete + * + * @return {Promise} + */ + remove: function(path) { + return this._simpleCall('DELETE', path); + }, + + /** + * Moves path to another path + * + * @param {String} path path to move + * @param {String} destinationPath destination path + * @param {boolean} [allowOverwrite=false] true to allow overwriting, + * false otherwise + * + * @return {Promise} promise + */ + move: function(path, destinationPath, allowOverwrite) { + if (!path) { + throw 'Missing argument "path"'; + } + if (!destinationPath) { + throw 'Missing argument "destinationPath"'; + } + + var self = this; + var deferred = $.Deferred(); + var promise = deferred.promise(); + var headers = + _.extend({ + 'Destination' : this._buildUrl(destinationPath) + }, this._defaultHeaders); + + if (!allowOverwrite) { + headers['Overwrite'] = 'F'; + } + + this._client.request( + 'MOVE', + this._buildUrl(path), + headers + ).then( + function(response) { + if (self._isSuccessStatus(response.status)) { + deferred.resolve(response.status); + } else { + deferred.reject(response.status); + } + } + ); + return promise; + } + + }; + + if (!OC.Files) { + /** + * @namespace OC.Files + * + * @since 8.2 + */ + OC.Files = {}; + } + + /** + * Returns the default instance of the files client + * + * @return {OC.Files.Client} default client + * + * @since 8.2 + */ + OC.Files.getClient = function() { + if (OC.Files._defaultClient) { + return OC.Files._defaultClient; + } + + var client = new OC.Files.Client({ + host: OC.getHost(), + port: OC.getPort(), + root: OC.linkToRemoteBase('webdav'), + useHTTPS: OC.getProtocol() === 'https' + }); + OC.Files._defaultClient = client; + return client; + }; + + OC.Files.Client = Client; +})(OC, OC.Files.FileInfo); + diff --git a/core/js/files/fileinfo.js b/core/js/files/fileinfo.js new file mode 100644 index 00000000000..95af07b7992 --- /dev/null +++ b/core/js/files/fileinfo.js @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +(function(OC) { + + /** + * @class OC.Files.FileInfo + * @classdesc File information + * + * @param {Object} data file data, see attributes for details + * + * @since 8.2 + */ + var FileInfo = function(data) { + if (!_.isUndefined(data.id)) { + this.id = parseInt(data.id, 10); + } + + // TODO: normalize path + this.path = data.path || ''; + this.name = data.name; + + this.mtime = data.mtime; + this.etag = data.etag; + this.permissions = data.permissions; + this.size = data.size; + this.mimetype = data.mimetype || 'application/octet-stream'; + this.mountType = data.mountType; + this.icon = data.icon; + this._props = data._props; + + if (data.type) { + this.type = data.type; + } else if (this.mimetype === 'httpd/unix-directory') { + this.type = 'dir'; + } else { + this.type = 'file'; + } + + if (!this.mimetype) { + if (this.type === 'dir') { + this.mimetype = 'httpd/unix-directory'; + } else { + this.mimetype = 'application/octet-stream'; + } + } + }; + + /** + * @memberof OC.Files + */ + FileInfo.prototype = { + /** + * File id + * + * @type int + */ + id: null, + + /** + * File name + * + * @type String + */ + name: null, + + /** + * Path leading to the file, without the file name, + * and with a leading slash. + * + * @type String + */ + path: null, + + /** + * Mime type + * + * @type String + */ + mimetype: null, + + /** + * Icon URL. + * + * Can be used to override the mime type icon. + * + * @type String + */ + icon: null, + + /** + * File type. 'file' for files, 'dir' for directories. + * + * @type String + * @deprecated rely on mimetype instead + */ + type: 'file', + + /** + * Permissions. + * + * @see OC#PERMISSION_ALL for permissions + * @type int + */ + permissions: null, + + /** + * Modification time + * + * @type int + */ + mtime: null, + + /** + * Etag + * + * @type String + */ + etag: null, + + /** + * Mount type. + * + * One of null, "external-root", "shared" or "shared-root" + * + * @type string + */ + mountType: null + }; + + if (!OC.Files) { + OC.Files = {}; + } + OC.Files.FileInfo = FileInfo; +})(OC); + diff --git a/core/js/js.js b/core/js/js.js index 57c9871233b..ce552bb8ea2 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1428,7 +1428,6 @@ function initCore() { $('body').delegate('#app-content', 'apprendered appresized', adjustControlsWidth); } - } $(document).ready(initCore); diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js index cd387d76ce8..f09a7054c9f 100644 --- a/core/js/tests/specHelper.js +++ b/core/js/tests/specHelper.js @@ -86,6 +86,7 @@ window.firstDay = 0; // setup dummy webroots /* jshint camelcase: false */ window.oc_debug = true; +// FIXME: oc_webroot is supposed to be only the path!!! window.oc_webroot = location.href + '/'; window.oc_appswebroots = { "files": window.oc_webroot + '/apps/files/' diff --git a/core/js/tests/specs/files/clientSpec.js b/core/js/tests/specs/files/clientSpec.js new file mode 100644 index 00000000000..67815d93f05 --- /dev/null +++ b/core/js/tests/specs/files/clientSpec.js @@ -0,0 +1,712 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2015 Vincent Petry +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library 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 library. If not, see . +* +*/ + +describe('OC.Files.Client tests', function() { + var Client = OC.Files.Client; + var baseUrl; + var client; + + beforeEach(function() { + baseUrl = 'https://testhost:999/owncloud/remote.php/webdav/'; + + client = new Client({ + host: 'testhost', + port: 999, + root: '/owncloud/remote.php/webdav', + useHTTPS: true + }); + }); + afterEach(function() { + client = null; + }); + + /** + * Send an status response and check that the given + * promise gets its success handler called with the error + * status code + * + * @param {Promise} promise promise + * @param {int} status status to test + */ + function respondAndCheckStatus(promise, status) { + var successHandler = sinon.stub(); + var failHandler = sinon.stub(); + promise.done(successHandler); + promise.fail(failHandler); + + fakeServer.requests[0].respond( + status, + {'Content-Type': 'application/xml'}, + '' + ); + + promise.then(function() { + expect(successHandler.calledOnce).toEqual(true); + expect(successHandler.getCall(0).args[0]).toEqual(status); + + expect(failHandler.notCalled).toEqual(true); + }); + + return promise; + } + + /** + * Send an error response and check that the given + * promise gets its fail handler called with the error + * status code + * + * @param {Promise} promise promise object + * @param {int} status error status to test + */ + function respondAndCheckError(promise, status) { + var successHandler = sinon.stub(); + var failHandler = sinon.stub(); + promise.done(successHandler); + promise.fail(failHandler); + + fakeServer.requests[0].respond( + status, + {'Content-Type': 'application/xml'}, + '' + ); + + promise.then(function() { + expect(failHandler.calledOnce).toEqual(true); + expect(failHandler.calledWith(status)).toEqual(true); + + expect(successHandler.notCalled).toEqual(true); + + fulfill(); + }); + + return promise; + } + + /** + * Returns a list of request properties parsed from the given request body. + * + * @param {string} requestBody request XML + * + * @return {Array.} array of request properties in the format + * "{NS:}propname" + */ + function getRequestedProperties(requestBody) { + var doc = (new window.DOMParser()).parseFromString( + requestBody, + 'application/xml' + ); + var propRoots = doc.getElementsByTagNameNS('DAV:', 'prop'); + var propsList = propRoots.item(0).childNodes; + return _.map(propsList, function(propNode) { + return '{' + propNode.namespaceURI + '}' + propNode.localName; + }); + } + + function makePropBlock(props) { + var s = '\n'; + + _.each(props, function(value, key) { + s += '<' + key + '>' + value + '\n'; + }); + + return s + '\n'; + } + + function makeResponseBlock(href, props, failedProps) { + var s = '\n'; + s += '' + href + '\n'; + s += '\n'; + s += makePropBlock(props); + s += 'HTTP/1.1 200 OK'; + s += '\n'; + if (failedProps) { + s += '\n'; + _.each(failedProps, function(prop) { + s += '<' + prop + '/>\n'; + }); + s += 'HTTP/1.1 404 Not Found\n'; + s += '\n'; + } + return s + '\n'; + } + + describe('file listing', function() { + + var folderContentsXml = + '' + + '' + + makeResponseBlock( + '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/', + { + 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT', + 'd:getetag': '"56cfcabd79abb"', + 'd:resourcetype': '', + 'oc:id': '00000011oc2d13a6a068', + 'oc:permissions': 'RDNVCK', + 'oc:size': 120 + }, + [ + 'd:getcontenttype', + 'd:getcontentlength' + ] + ) + + makeResponseBlock( + '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt', + { + 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT', + 'd:getetag': '"559fcabd79a38"', + 'd:getcontenttype': 'text/plain', + 'd:getcontentlength': 250, + 'd:resourcetype': '', + 'oc:id': '00000051oc2d13a6a068', + 'oc:permissions': 'RDNVW' + }, + [ + 'oc:size', + ] + ) + + makeResponseBlock( + '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/sub', + { + 'd:getlastmodified': 'Fri, 10 Jul 2015 14:00:00 GMT', + 'd:getetag': '"66cfcabd79abb"', + 'd:resourcetype': '', + 'oc:id': '00000015oc2d13a6a068', + 'oc:permissions': 'RDNVCK', + 'oc:size': 100 + }, + [ + 'd:getcontenttype', + 'd:getcontentlength' + ] + ) + + ''; + + it('sends PROPFIND with explicit properties to get file list', function() { + client.getFolderContents('path/to space/文件夹'); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('PROPFIND'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(fakeServer.requests[0].requestHeaders.Depth).toEqual(1); + + var props = getRequestedProperties(fakeServer.requests[0].requestBody); + expect(props).toContain('{DAV:}getlastmodified'); + expect(props).toContain('{DAV:}getcontentlength'); + expect(props).toContain('{DAV:}getcontenttype'); + expect(props).toContain('{DAV:}getetag'); + expect(props).toContain('{DAV:}resourcetype'); + expect(props).toContain('{http://owncloud.org/ns}id'); + expect(props).toContain('{http://owncloud.org/ns}size'); + expect(props).toContain('{http://owncloud.org/ns}permissions'); + }); + it('sends PROPFIND to base url when empty path given', function() { + client.getFolderContents(''); + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].url).toEqual(baseUrl); + }); + it('sends PROPFIND to base url when root path given', function() { + client.getFolderContents('/'); + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].url).toEqual(baseUrl); + }); + it('parses the result list into a FileInfo array', function() { + var promise = client.getFolderContents('path/to space/文件夹'); + + expect(fakeServer.requests.length).toEqual(1); + + fakeServer.requests[0].respond( + 207, + {'Content-Type': 'application/xml'}, + folderContentsXml + ); + + promise.then(function(status, response) { + expect(status).toEqual(207); + expect(_.isArray(response)).toEqual(true); + + expect(response.length).toEqual(2); + + // file entry + var info = response[0]; + expect(info instanceof OC.Files.FileInfo).toEqual(true); + expect(info.id).toEqual(51); + expect(info.path).toEqual('/path/to space/文件夹'); + expect(info.name).toEqual('One.txt'); + expect(info.permissions).toEqual(31); + expect(info.size).toEqual(250); + expect(info.mtime.getTime()).toEqual(1436535485000); + expect(info.mimetype).toEqual('text/plain'); + expect(info.etag).toEqual('559fcabd79a38'); + + // sub entry + info = response[1]; + expect(info instanceof OC.Files.FileInfo).toEqual(true); + expect(info.id).toEqual(15); + expect(info.path).toEqual('/path/to space/文件夹'); + expect(info.name).toEqual('sub'); + expect(info.permissions).toEqual(31); + expect(info.size).toEqual(100); + expect(info.mtime.getTime()).toEqual(1436536800000); + expect(info.mimetype).toEqual('httpd/unix-directory'); + expect(info.etag).toEqual('66cfcabd79abb'); + }); + return promise.promise(); + }); + it('returns parent node in result if specified', function() { + var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true}); + + expect(fakeServer.requests.length).toEqual(1); + + fakeServer.requests[0].respond( + 207, + {'Content-Type': 'application/xml'}, + folderContentsXml + ); + + promise.then(function(status, response) { + expect(status).toEqual(207); + expect(_.isArray(response)).toEqual(true); + + expect(response.length).toEqual(3); + + // root entry + var info = response[0]; + expect(info instanceof OC.Files.FileInfo).toEqual(true); + expect(info.id).toEqual(11); + expect(info.path).toEqual('/path/to space'); + expect(info.name).toEqual('文件夹'); + expect(info.permissions).toEqual(31); + expect(info.size).toEqual(120); + expect(info.mtime.getTime()).toEqual(1436522405000); + expect(info.mimetype).toEqual('httpd/unix-directory'); + expect(info.etag).toEqual('56cfcabd79abb'); + + // the two other entries follow + expect(response[1].id).toEqual(51); + expect(response[2].id).toEqual(15); + }); + + return promise; + }); + it('rejects promise when an error occurred', function() { + var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true}); + return respondAndCheckError(promise, 404); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); + + describe('file info', function() { + var responseXml = + '' + + '' + + makeResponseBlock( + '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/', + { + 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT', + 'd:getetag': '"56cfcabd79abb"', + 'd:resourcetype': '', + 'oc:id': '00000011oc2d13a6a068', + 'oc:permissions': 'RDNVCK', + 'oc:size': 120 + }, + [ + 'd:getcontenttype', + 'd:getcontentlength' + ] + ) + + ''; + + it('sends PROPFIND with zero depth to get single file info', function() { + client.getFileInfo('path/to space/文件夹'); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('PROPFIND'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(fakeServer.requests[0].requestHeaders.Depth).toEqual(0); + + var props = getRequestedProperties(fakeServer.requests[0].requestBody); + expect(props).toContain('{DAV:}getlastmodified'); + expect(props).toContain('{DAV:}getcontentlength'); + expect(props).toContain('{DAV:}getcontenttype'); + expect(props).toContain('{DAV:}getetag'); + expect(props).toContain('{DAV:}resourcetype'); + expect(props).toContain('{http://owncloud.org/ns}id'); + expect(props).toContain('{http://owncloud.org/ns}size'); + expect(props).toContain('{http://owncloud.org/ns}permissions'); + }); + it('parses the result into a FileInfo', function() { + var promise = client.getFileInfo('path/to space/文件夹'); + + expect(fakeServer.requests.length).toEqual(1); + + fakeServer.requests[0].respond( + 207, + {'Content-Type': 'application/xml'}, + responseXml + ); + + promise.then(function(status, response) { + expect(status).toEqual(207); + expect(_.isArray(response)).toEqual(false); + + var info = response; + expect(info instanceof OC.Files.FileInfo).toEqual(true); + expect(info.id).toEqual(11); + expect(info.path).toEqual('/path/to space'); + expect(info.name).toEqual('文件夹'); + expect(info.permissions).toEqual(31); + expect(info.size).toEqual(120); + expect(info.mtime.getTime()).toEqual(1436522405000); + expect(info.mimetype).toEqual('httpd/unix-directory'); + expect(info.etag).toEqual('56cfcabd79abb'); + }); + + return promise; + }); + it('properly parses entry inside root', function() { + var responseXml = + '' + + '' + + makeResponseBlock( + '/owncloud/remote.php/webdav/in%20root', + { + 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT', + 'd:getetag': '"56cfcabd79abb"', + 'd:resourcetype': '', + 'oc:id': '00000011oc2d13a6a068', + 'oc:permissions': 'RDNVCK', + 'oc:size': 120 + }, + [ + 'd:getcontenttype', + 'd:getcontentlength' + ] + ) + + ''; + + var promise = client.getFileInfo('in root'); + + expect(fakeServer.requests.length).toEqual(1); + + fakeServer.requests[0].respond( + 207, + {'Content-Type': 'application/xml'}, + responseXml + ); + + promise.then(function(status, response) { + expect(status).toEqual(207); + expect(_.isArray(response)).toEqual(false); + + var info = response; + expect(info instanceof OC.Files.FileInfo).toEqual(true); + expect(info.id).toEqual(11); + expect(info.path).toEqual('/'); + expect(info.name).toEqual('in root'); + expect(info.permissions).toEqual(31); + expect(info.size).toEqual(120); + expect(info.mtime.getTime()).toEqual(1436522405000); + expect(info.mimetype).toEqual('httpd/unix-directory'); + expect(info.etag).toEqual('56cfcabd79abb'); + }); + + return promise; + }); + it('rejects promise when an error occurred', function() { + var promise = client.getFileInfo('path/to space/文件夹'); + return respondAndCheckError(promise, 404); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); + + describe('permissions', function() { + + function getFileInfoWithPermission(webdavPerm, isFile) { + var props = { + 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT', + 'd:getetag': '"559fcabd79a38"', + 'd:getcontentlength': 250, + 'oc:id': '00000051oc2d13a6a068', + 'oc:permissions': webdavPerm, + }; + + if (isFile) { + props['d:getcontenttype'] = 'text/plain'; + } else { + props['d:resourcetype'] = ''; + } + + var responseXml = + '' + + '' + + makeResponseBlock( + '/owncloud/remote.php/webdav/file.txt', + props + ) + + ''; + var promise = client.getFileInfo('file.txt'); + + expect(fakeServer.requests.length).toEqual(1); + fakeServer.requests[0].respond( + 207, + {'Content-Type': 'application/xml'}, + responseXml + ); + + fakeServer.restore(); + fakeServer = sinon.fakeServer.create(); + + return promise; + } + + function testPermission(permission, isFile, expectedPermissions) { + var promise = getFileInfoWithPermission(permission, isFile); + promise.then(function(result) { + expect(result.permissions).toEqual(expectedPermissions); + }); + return promise; + } + + function testMountType(permission, isFile, expectedMountType) { + var promise = getFileInfoWithPermission(permission, isFile); + promise.then(function(result) { + expect(result.mountType).toEqual(expectedMountType); + }); + return promise; + } + + it('properly parses file permissions', function() { + // permission, isFile, expectedPermissions + var testCases = [ + ['', true, OC.PERMISSION_READ], + ['C', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE], + ['K', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE], + ['W', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE], + ['D', true, OC.PERMISSION_READ | OC.PERMISSION_DELETE], + ['R', true, OC.PERMISSION_READ | OC.PERMISSION_SHARE], + ['CKWDR', true, OC.PERMISSION_ALL] + ]; + return Promise.all( + _.map(testCases, function(testCase) { + return testPermission.apply(testCase); + }) + ); + }); + it('properly parses folder permissions', function() { + var testCases = [ + ['', false, OC.PERMISSION_READ], + ['C', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE], + ['K', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE], + ['W', false, OC.PERMISSION_READ | OC.PERMISSION_UPDATE], + ['D', false, OC.PERMISSION_READ | OC.PERMISSION_DELETE], + ['R', false, OC.PERMISSION_READ | OC.PERMISSION_SHARE], + ['CKWDR', false, OC.PERMISSION_ALL] + ]; + + return Promise.all( + _.map(testCases, function(testCase) { + return testPermission.apply(testCase); + }) + ); + }); + it('properly parses mount types', function() { + var testCases = [ + ['CKWDR', false, null], + ['M', false, 'external'], + ['S', false, 'shared'], + ['SM', false, 'shared'] + ]; + + return Promise.all( + _.map(testCases, function(testCase) { + return testMountType.apply(testCase); + }) + ); + }); + }); + + describe('get file contents', function() { + it('returns file contents', function() { + var promise = client.getFileContents('path/to space/文件夹/One.txt'); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('GET'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); + + fakeServer.requests[0].respond( + 200, + {'Content-Type': 'text/plain'}, + 'some contents' + ); + + promise.then(function(status, response) { + expect(status).toEqual(200); + expect(response).toEqual('some contents'); + }); + + return promise; + }); + it('rejects promise when an error occurred', function() { + var promise = client.getFileContents('path/to space/文件夹/One.txt'); + return respondAndCheckError(promise, 409); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); + + describe('put file contents', function() { + it('sends PUT with file contents', function() { + var promise = client.putFileContents( + 'path/to space/文件夹/One.txt', + 'some contents' + ); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('PUT'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); + expect(fakeServer.requests[0].requestBody).toEqual('some contents'); + expect(fakeServer.requests[0].requestHeaders['If-None-Match']).toEqual('*'); + expect(fakeServer.requests[0].requestHeaders['Content-Type']).toEqual('text/plain;charset=utf-8'); + + return respondAndCheckStatus(promise, 201); + }); + it('sends PUT with file contents with headers matching options', function() { + var promise = client.putFileContents( + 'path/to space/文件夹/One.txt', + 'some contents', + { + overwrite: false, + contentType: 'text/markdown' + } + ); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('PUT'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); + expect(fakeServer.requests[0].requestBody).toEqual('some contents'); + expect(fakeServer.requests[0].requestHeaders['If-None-Match']).not.toBeDefined(); + expect(fakeServer.requests[0].requestHeaders['Content-Type']).toEqual('text/markdown;charset=utf-8'); + + return respondAndCheckStatus(promise, 201); + }); + it('rejects promise when an error occurred', function() { + var promise = client.putFileContents( + 'path/to space/文件夹/One.txt', + 'some contents' + ); + return respondAndCheckError(promise, 409); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); + + describe('create directory', function() { + it('sends MKCOL with specified path', function() { + var promise = client.createDirectory('path/to space/文件夹/new dir'); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('MKCOL'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir'); + + return respondAndCheckStatus(promise, 201); + }); + it('rejects promise when an error occurred', function() { + var promise = client.createDirectory('path/to space/文件夹/new dir'); + return respondAndCheckError(promise, 404); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); + + describe('deletion', function() { + it('sends DELETE with specified path', function() { + var promise = client.remove('path/to space/文件夹'); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('DELETE'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + + return respondAndCheckStatus(promise, 201); + }); + it('rejects promise when an error occurred', function() { + var promise = client.remove('path/to space/文件夹'); + return respondAndCheckError(promise, 404); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); + + describe('move', function() { + it('sends MOVE with specified paths with fail on overwrite by default', function() { + var promise = client.move( + 'path/to space/文件夹', + 'path/to space/anotherdir/文件夹' + ); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('MOVE'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(fakeServer.requests[0].requestHeaders.Destination) + .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(fakeServer.requests[0].requestHeaders.Overwrite) + .toEqual('F'); + + return respondAndCheckStatus(promise, 201); + }); + it('sends MOVE with silent overwrite mode when specified', function() { + var promise = client.move( + 'path/to space/文件夹', + 'path/to space/anotherdir/文件夹', + {allowOverwrite: true} + ); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('MOVE'); + expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(fakeServer.requests[0].requestHeaders.Destination) + .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(fakeServer.requests[0].requestHeaders.Overwrite) + .not.toBeDefined(); + + return respondAndCheckStatus(promise, 201); + }); + it('rejects promise when an error occurred', function() { + var promise = client.move( + 'path/to space/文件夹', + 'path/to space/anotherdir/文件夹', + {allowOverwrite: true} + ); + return respondAndCheckError(promise, 404); + }); + it('throws exception if arguments are missing', function() { + // TODO + }); + }); +}); diff --git a/tests/karma.config.js b/tests/karma.config.js index 64a94ef230b..dc621ae0f74 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -164,15 +164,15 @@ module.exports = function(config) { // need to test the core app as well ? if (testCore) { // core tests - files.push(corePath + 'tests/specs/*.js'); + files.push(corePath + 'tests/specs/**/*.js'); } function addApp(app) { // if only a string was specified, expand to structure if (typeof(app) === 'string') { app = { - srcFiles: 'apps/' + app + '/js/*.js', - testFiles: 'apps/' + app + '/tests/js/*.js' + srcFiles: 'apps/' + app + '/js/**/*.js', + testFiles: 'apps/' + app + '/tests/js/**/*.js' }; } -- GitLab From fa2be0750c50de45a2fd101eb23fa858c0e0771b Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 13 Jul 2015 17:38:13 +0200 Subject: [PATCH 125/344] Make files app use Webdav for most operations --- apps/files/ajax/delete.php | 81 -- apps/files/ajax/move.php | 59 -- apps/files/ajax/newfile.php | 103 --- apps/files/ajax/newfolder.php | 99 -- apps/files/ajax/rename.php | 58 -- apps/files/js/app.js | 3 +- apps/files/js/fileactions.js | 3 +- apps/files/js/filelist.js | 572 ++++++------ apps/files/js/files.js | 30 +- apps/files/lib/app.php | 88 +- apps/files/lib/helper.php | 3 - apps/files/tests/ajax_rename.php | 232 ----- apps/files/tests/js/favoritesfilelistspec.js | 3 +- apps/files/tests/js/fileUploadSpec.js | 2 + apps/files/tests/js/fileactionsSpec.js | 2 +- apps/files/tests/js/fileactionsmenuSpec.js | 7 +- apps/files/tests/js/filelistSpec.js | 843 ++++++++---------- apps/files/tests/js/filesSpec.js | 6 +- apps/files_sharing/js/sharedfilelist.js | 4 +- .../tests/js/sharedfilelistSpec.js | 26 +- apps/files_trashbin/js/filelist.js | 72 +- core/js/oc-dialogs.js | 2 +- 22 files changed, 828 insertions(+), 1470 deletions(-) delete mode 100644 apps/files/ajax/delete.php delete mode 100644 apps/files/ajax/move.php delete mode 100644 apps/files/ajax/newfile.php delete mode 100644 apps/files/ajax/newfolder.php delete mode 100644 apps/files/ajax/rename.php delete mode 100644 apps/files/tests/ajax_rename.php diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php deleted file mode 100644 index 2d02869df14..00000000000 --- a/apps/files/ajax/delete.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @author Frank Karlitschek - * @author Jakob Sack - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ -OCP\JSON::checkLoggedIn(); -OCP\JSON::callCheck(); -\OC::$server->getSession()->close(); - - -// Get data -$dir = isset($_POST['dir']) ? (string)$_POST['dir'] : ''; -$allFiles = isset($_POST["allfiles"]) ? (string)$_POST["allfiles"] : false; - -// delete all files in dir ? -if ($allFiles === 'true') { - $files = array(); - $fileList = \OC\Files\Filesystem::getDirectoryContent($dir); - foreach ($fileList as $fileInfo) { - $files[] = $fileInfo['name']; - } -} else { - $files = isset($_POST["file"]) ? (string)$_POST["file"] : (string)$_POST["files"]; - $files = json_decode($files); -} -$filesWithError = ''; - -$success = true; - -//Now delete -foreach ($files as $file) { - try { - if (\OC\Files\Filesystem::file_exists($dir . '/' . $file) && - !(\OC\Files\Filesystem::isDeletable($dir . '/' . $file) && - \OC\Files\Filesystem::unlink($dir . '/' . $file)) - ) { - $filesWithError .= $file . "\n"; - $success = false; - } - } catch (\Exception $e) { - $filesWithError .= $file . "\n"; - $success = false; - } -} - -// get array with updated storage stats (e.g. max file size) after upload -try { - $storageStats = \OCA\Files\Helper::buildFileStorageStatistics($dir); -} catch(\OCP\Files\NotFoundException $e) { - OCP\JSON::error(['data' => ['message' => 'File not found']]); - return; -} - -if ($success) { - OCP\JSON::success(array("data" => array_merge(array("dir" => $dir, "files" => $files), $storageStats))); -} else { - OCP\JSON::error(array("data" => array_merge(array("message" => "Could not delete:\n" . $filesWithError), $storageStats))); -} diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php deleted file mode 100644 index 0961636a116..00000000000 --- a/apps/files/ajax/move.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @author Frank Karlitschek - * @author Georg Ehrke - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ -OCP\JSON::checkLoggedIn(); -OCP\JSON::callCheck(); -\OC::$server->getSession()->close(); - -// Get data -$dir = isset($_POST['dir']) ? (string)$_POST['dir'] : ''; -$file = isset($_POST['file']) ? (string)$_POST['file'] : ''; -$target = isset($_POST['target']) ? rawurldecode((string)$_POST['target']) : ''; - -$l = \OC::$server->getL10N('files'); - -if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) { - OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s - File with this name already exists", array($file)) ))); - exit; -} - -if ($target != '' || strtolower($file) != 'shared') { - $targetFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); - $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); - try { - if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { - OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file ))); - } else { - OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s", array($file)) ))); - } - } catch (\OCP\Files\NotPermittedException $e) { - OCP\JSON::error(array("data" => array( "message" => $l->t("Permission denied") ))); - } catch (\Exception $e) { - OCP\JSON::error(array("data" => array( "message" => $e->getMessage()))); - } -}else{ - OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s", array($file)) ))); -} diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php deleted file mode 100644 index be09b288d4b..00000000000 --- a/apps/files/ajax/newfile.php +++ /dev/null @@ -1,103 +0,0 @@ - - * @author Georg Ehrke - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ -// Init owncloud -global $eventSource; - -\OCP\JSON::checkLoggedIn(); -\OCP\JSON::callCheck(); - -\OC::$server->getSession()->close(); - -// Get the params -$dir = isset( $_REQUEST['dir'] ) ? '/'.trim((string)$_REQUEST['dir'], '/\\') : ''; -$fileName = isset( $_REQUEST['filename'] ) ? trim((string)$_REQUEST['filename'], '/\\') : ''; - -$l10n = \OC::$server->getL10N('files'); - -$result = array( - 'success' => false, - 'data' => NULL -); - -try { - \OC\Files\Filesystem::getView()->verifyPath($dir, $fileName); -} catch (\OCP\Files\InvalidPathException $ex) { - $result['data'] = [ - 'message' => $ex->getMessage()]; - OCP\JSON::error($result); - return; -} - -if (!\OC\Files\Filesystem::file_exists($dir . '/')) { - $result['data'] = array('message' => (string)$l10n->t( - 'The target folder has been moved or deleted.'), - 'code' => 'targetnotfound' - ); - OCP\JSON::error($result); - exit(); -} - -$target = $dir.'/'.$fileName; - -if (\OC\Files\Filesystem::file_exists($target)) { - $result['data'] = array('message' => (string)$l10n->t( - 'The name %s is already used in the folder %s. Please choose a different name.', - array($fileName, $dir)) - ); - OCP\JSON::error($result); - exit(); -} - -$success = false; -$templateManager = OC_Helper::getFileTemplateManager(); -$mimeType = OC_Helper::getMimetypeDetector()->detectPath($target); -$content = $templateManager->getTemplate($mimeType); - -try { - if($content) { - $success = \OC\Files\Filesystem::file_put_contents($target, $content); - } else { - $success = \OC\Files\Filesystem::touch($target); - } -} catch (\Exception $e) { - $result = [ - 'success' => false, - 'data' => [ - 'message' => $e->getMessage() - ] - ]; - OCP\JSON::error($result); - exit(); -} - -if($success) { - $meta = \OC\Files\Filesystem::getFileInfo($target); - OCP\JSON::success(array('data' => \OCA\Files\Helper::formatFileInfo($meta))); - return; -} - -OCP\JSON::error(array('data' => array( 'message' => $l10n->t('Error when creating the file') ))); diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php deleted file mode 100644 index a2897dd437a..00000000000 --- a/apps/files/ajax/newfolder.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @author Björn Schießle - * @author Frank Karlitschek - * @author Georg Ehrke - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ -// Init owncloud - - -OCP\JSON::checkLoggedIn(); -OCP\JSON::callCheck(); -\OC::$server->getSession()->close(); - -// Get the params -$dir = isset($_POST['dir']) ? (string)$_POST['dir'] : ''; -$folderName = isset($_POST['foldername']) ?(string) $_POST['foldername'] : ''; - -$l10n = \OC::$server->getL10N('files'); - -$result = array( - 'success' => false, - 'data' => NULL - ); - -try { - \OC\Files\Filesystem::getView()->verifyPath($dir, $folderName); -} catch (\OCP\Files\InvalidPathException $ex) { - $result['data'] = [ - 'message' => $ex->getMessage()]; - OCP\JSON::error($result); - return; -} - -if (!\OC\Files\Filesystem::file_exists($dir . '/')) { - $result['data'] = array('message' => (string)$l10n->t( - 'The target folder has been moved or deleted.'), - 'code' => 'targetnotfound' - ); - OCP\JSON::error($result); - exit(); -} - -$target = $dir . '/' . $folderName; - -if (\OC\Files\Filesystem::file_exists($target)) { - $result['data'] = array('message' => $l10n->t( - 'The name %s is already used in the folder %s. Please choose a different name.', - array($folderName, $dir)) - ); - OCP\JSON::error($result); - exit(); -} - -try { - if(\OC\Files\Filesystem::mkdir($target)) { - if ( $dir !== '/') { - $path = $dir.'/'.$folderName; - } else { - $path = '/'.$folderName; - } - $meta = \OC\Files\Filesystem::getFileInfo($path); - $meta['type'] = 'dir'; // missing ?! - OCP\JSON::success(array('data' => \OCA\Files\Helper::formatFileInfo($meta))); - exit(); - } -} catch (\Exception $e) { - $result = [ - 'success' => false, - 'data' => [ - 'message' => $e->getMessage() - ] - ]; - OCP\JSON::error($result); - exit(); -} - -OCP\JSON::error(array('data' => array( 'message' => $l10n->t('Error when creating the folder') ))); diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php deleted file mode 100644 index a24a57b1046..00000000000 --- a/apps/files/ajax/rename.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @author Frank Karlitschek - * @author Jakob Sack - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ - -OCP\JSON::checkLoggedIn(); -OCP\JSON::callCheck(); -\OC::$server->getSession()->close(); - -$l10n = \OC::$server->getL10N('files'); - -$files = new \OCA\Files\App( - \OC\Files\Filesystem::getView(), - \OC::$server->getL10N('files') -); -try { - $result = $files->rename( - isset($_GET['dir']) ? (string)$_GET['dir'] : '', - isset($_GET['file']) ? (string)$_GET['file'] : '', - isset($_GET['newname']) ? (string)$_GET['newname'] : '' - ); -} catch (\Exception $e) { - $result = [ - 'success' => false, - 'data' => [ - 'message' => $e->getMessage() - ] - ]; -} - -if($result['success'] === true){ - OCP\JSON::success(['data' => $result['data']]); -} else { - OCP\JSON::error(['data' => $result['data']]); -} diff --git a/apps/files/js/app.js b/apps/files/js/app.js index f31770466fe..ff505d417f1 100644 --- a/apps/files/js/app.js +++ b/apps/files/js/app.js @@ -71,7 +71,8 @@ folderDropOptions: folderDropOptions, fileActions: fileActions, allowLegacyActions: true, - scrollTo: urlParams.scrollto + scrollTo: urlParams.scrollto, + filesClient: OC.Files.getClient() } ); this.files.initialize(); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 6a767d48a28..32385c42478 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -575,7 +575,8 @@ }, actionHandler: function (filename, context) { var dir = context.dir || context.fileList.getCurrentDirectory(); - var url = context.fileList.getDownloadUrl(filename, dir); + var isDir = context.$file.attr('data-type') === 'dir'; + var url = context.fileList.getDownloadUrl(filename, dir, isDir); var downloadFileaction = $(context.$file).find('.fileactions .action-download'); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index d1f68d98eab..2c97816df00 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -22,11 +22,12 @@ * * @param $el container element with existing markup for the #controls * and a table - * @param [options] map of options, see other parameters - * @param [options.scrollContainer] scrollable container, defaults to $(window) - * @param [options.dragOptions] drag options, disabled by default - * @param [options.folderDropOptions] folder drop options, disabled by default - * @param [options.detailsViewEnabled=true] whether to enable details view + * @param {Object} [options] map of options, see other parameters + * @param {Object} [options.scrollContainer] scrollable container, defaults to $(window) + * @param {Object} [options.dragOptions] drag options, disabled by default + * @param {Object} [options.folderDropOptions] folder drop options, disabled by default + * @param {boolean} [options.detailsViewEnabled=true] whether to enable details view + * @param {OC.Files.Client} [options.filesClient] files client to use */ var FileList = function($el, options) { this.initialize($el, options); @@ -73,6 +74,13 @@ */ _detailsView: null, + /** + * Files client instance + * + * @type OC.Files.Client + */ + filesClient: null, + /** * Whether the file list was initialized already. * @type boolean @@ -92,10 +100,17 @@ * Array of files in the current folder. * The entries are of file data. * - * @type Array. + * @type Array. */ files: [], + /** + * Current directory entry + * + * @type OC.Files.FileInfo + */ + dirInfo: null, + /** * File actions handler, defaults to OCA.Files.FileActions * @type OCA.Files.FileActions @@ -149,7 +164,7 @@ * When false, clicking on a table header will call reload(). * When true, clicking on a table header will simply resort the list. */ - _clientSideSort: false, + _clientSideSort: true, /** * Current directory @@ -170,6 +185,7 @@ * @param options.dragOptions drag options, disabled by default * @param options.folderDropOptions folder drop options, disabled by default * @param options.scrollTo name of file to scroll to after the first load + * @param {OC.Files.Client} [options.filesClient] files API client * @private */ initialize: function($el, options) { @@ -185,6 +201,12 @@ if (options.folderDropOptions) { this._folderDropOptions = options.folderDropOptions; } + if (options.filesClient) { + this.filesClient = options.filesClient; + } else { + // default client if not specified + this.filesClient = OC.Files.getClient(); + } this.$el = $el; if (options.id) { @@ -209,6 +231,8 @@ this.files = []; this._selectedFiles = {}; this._selectionSummary = new OCA.Files.FileSummary(); + // dummy root dir info + this.dirInfo = new OC.Files.FileInfo({}); this.fileSummary = this._createSummary(); @@ -359,7 +383,7 @@ var highlightState = $tr.hasClass('highlighted'); $tr = self.updateRow( $tr, - _.extend({isPreviewAvailable: true}, model.toJSON()), + model.toJSON(), {updateSummary: true, silent: false, animate: true} ); $tr.toggleClass('highlighted', highlightState); @@ -618,7 +642,7 @@ }; OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, true); - OCA.Files.Files.handleDownload(this.getDownloadUrl(files, dir), disableLoadingState); + OCA.Files.Files.handleDownload(this.getDownloadUrl(files, dir, true), disableLoadingState); return false; }, @@ -894,16 +918,39 @@ self.$el.closest('#app-content').trigger(jQuery.Event('apprendered')); }); }, + + /** + * Returns the icon URL matching the given file info + * + * @param {OC.Files.FileInfo} fileInfo file info + * + * @return {string} icon URL + */ + _getIconUrl: function(fileInfo) { + var mimeType = fileInfo.mimetype || 'application/octet-stream'; + if (mimeType === 'httpd/unix-directory') { + // use default folder icon + if (fileInfo.mountType === 'shared' || fileInfo.mountType === 'shared-root') { + return OC.MimeType.getIconUrl('dir-shared'); + } else if (fileInfo.mountType === 'external-root') { + return OC.MimeType.getIconUrl('dir-external'); + } + return OC.MimeType.getIconUrl('dir'); + } + return OC.MimeType.getIconUrl(mimeType); + }, + /** * Creates a new table row element using the given file data. - * @param {OCA.Files.FileInfo} fileData file info attributes + * @param {OC.Files.FileInfo} fileData file info attributes * @param options map of attributes * @return new tr element (not appended to the table) */ _createRow: function(fileData, options) { var td, simpleSize, basename, extension, sizeColor, - icon = OC.MimeType.getIconUrl(fileData.mimetype), + icon = fileData.icon || this._getIconUrl(fileData), name = fileData.name, + // TODO: get rid of type, only use mime type type = fileData.type || 'file', mtime = parseInt(fileData.mtime, 10), mime = fileData.mimetype, @@ -943,6 +990,14 @@ } if (fileData.mountType) { + // FIXME: HACK: detect shared-root + if (fileData.mountType === 'shared' && this.dirInfo.mountType !== 'shared') { + // if parent folder isn't share, assume the displayed folder is a share root + fileData.mountType = 'shared-root'; + } else if (fileData.mountType === 'external' && this.dirInfo.mountType !== 'external') { + // if parent folder isn't external, assume the displayed folder is the external storage root + fileData.mountType = 'external-root'; + } tr.attr('data-mounttype', fileData.mountType); } @@ -953,24 +1008,16 @@ path = this.getCurrentDirectory(); } - if (type === 'dir') { - // use default folder icon - icon = icon || OC.imagePath('core', 'filetypes/folder'); - } - else { - icon = icon || OC.imagePath('core', 'filetypes/file'); - } - // filename td td = $(''); // linkUrl - if (type === 'dir') { + if (mime === 'httpd/unix-directory') { linkUrl = this.linkTo(path + '/' + name); } else { - linkUrl = this.getDownloadUrl(name, path); + linkUrl = this.getDownloadUrl(name, path, type === 'dir'); } if (this._allowSelection) { td.append( @@ -996,7 +1043,7 @@ basename = ''; extension = name; // split extension from filename for non dirs - } else if (type !== 'dir' && name.indexOf('.') !== -1) { + } else if (mime !== 'httpd/unix-directory' && name.indexOf('.') !== -1) { basename = name.substr(0, name.lastIndexOf('.')); extension = name.substr(name.lastIndexOf('.')); } else { @@ -1018,7 +1065,7 @@ nameSpan.tooltip({placement: 'right'}); } // dirs can show the number of uploaded files - if (type === 'dir') { + if (mime !== 'httpd/unix-directory') { linkElem.append($('').attr({ 'class': 'uploadtext', 'currentUploads': 0 @@ -1074,7 +1121,7 @@ * Adds an entry to the files array and also into the DOM * in a sorted manner. * - * @param {OCA.Files.FileInfo} fileData map of file attributes + * @param {OC.Files.FileInfo} fileData map of file attributes * @param {Object} [options] map of attributes * @param {boolean} [options.updateSummary] true to update the summary * after adding (default), false otherwise. Defaults to true. @@ -1147,7 +1194,7 @@ * Creates a new row element based on the given attributes * and returns it. * - * @param {OCA.Files.FileInfo} fileData map of file attributes + * @param {OC.Files.FileInfo} fileData map of file attributes * @param {Object} [options] map of attributes * @param {int} [options.index] index at which to insert the element * @param {boolean} [options.updateSummary] true to update the summary @@ -1182,7 +1229,7 @@ filenameTd.draggable(this._dragOptions); } // allow dropping on folders - if (this._folderDropOptions && fileData.type === 'dir') { + if (this._folderDropOptions && mime === 'httpd/unix-directory') { filenameTd.droppable(this._folderDropOptions); } @@ -1193,7 +1240,7 @@ // display actions this.fileActions.display(filenameTd, !options.silent, this); - if (fileData.isPreviewAvailable && mime !== 'httpd/unix-directory') { + if (mime !== 'httpd/unix-directory') { var iconDiv = filenameTd.find('.thumbnail'); // lazy load / newly inserted td ? // the typeof check ensures that the default value of animate is true @@ -1343,17 +1390,7 @@ this._currentFileModel = null; this.$el.find('.select-all').prop('checked', false); this.showMask(); - if (this._reloadCall) { - this._reloadCall.abort(); - } - this._reloadCall = $.ajax({ - url: this.getAjaxUrl('list'), - data: { - dir : this.getCurrentDirectory(), - sort: this._sort, - sortdirection: this._sortDirection - } - }); + this._reloadCall = this.filesClient.getFolderContents(this.getCurrentDirectory(), {includeParent: true}); if (this._detailsView) { // close sidebar this._updateDetailsView(null); @@ -1361,24 +1398,19 @@ var callBack = this.reloadCallback.bind(this); return this._reloadCall.then(callBack, callBack); }, - reloadCallback: function(result) { + reloadCallback: function(status, result) { delete this._reloadCall; this.hideMask(); - if (!result || result.status === 'error') { - // if the error is not related to folder we're trying to load, reload the page to handle logout etc - if (result.data.error === 'authentication_error' || - result.data.error === 'token_expired' || - result.data.error === 'application_not_enabled' - ) { - OC.redirect(OC.generateUrl('apps/files')); - } - OC.Notification.showTemporary(result.data.message); + if (status === 401) { + // TODO: append current URL to be able to get back after logging in again + OC.redirect(OC.generateUrl('apps/files')); + OC.Notification.show(result); return false; } // Firewall Blocked request? - if (result.status === 403) { + if (status === 403) { // Go home this.changeDirectory('/'); OC.Notification.showTemporary(t('files', 'This operation is forbidden')); @@ -1386,32 +1418,49 @@ } // Did share service die or something else fail? - if (result.status === 500) { + if (status === 500) { // Go home this.changeDirectory('/'); - OC.Notification.showTemporary(t('files', 'This directory is unavailable, please check the logs or contact the administrator')); + OC.Notification.showTemporary( + t('files', 'This directory is unavailable, please check the logs or contact the administrator') + ); + return false; + } + + if (status === 503) { + // Go home + if (this.getCurrentDirectory() !== '/') { + this.changeDirectory('/'); + // TODO: read error message from exception + OC.Notification.showTemporary( + t('files', 'Storage not available') + ); + } return false; } - if (result.status === 404) { + if (status === 404) { // go back home this.changeDirectory('/'); return false; } // aborted ? - if (result.status === 0){ + if (status === 0){ return true; } - // TODO: should rather return upload file size through - // the files list ajax call + // TODO: parse remaining quota from PROPFIND response this.updateStorageStatistics(true); - if (result.data.permissions) { - this.setDirectoryPermissions(result.data.permissions); + // first entry is the root + this.dirInfo = result.shift(); + + if (this.dirInfo.permissions) { + this.setDirectoryPermissions(this.dirInfo.permissions); } - this.setFiles(result.data.files); + result.sort(this._sortComparator); + this.setFiles(result); return true; }, @@ -1419,12 +1468,15 @@ OCA.Files.Files.updateStorageStatistics(this.getCurrentDirectory(), force); }, + /** + * @deprecated do not use nor override + */ getAjaxUrl: function(action, params) { return OCA.Files.Files.getAjaxUrl(action, params); }, - getDownloadUrl: function(files, dir) { - return OCA.Files.Files.getDownloadUrl(files, dir || this.getCurrentDirectory()); + getDownloadUrl: function(files, dir, isDir) { + return OCA.Files.Files.getDownloadUrl(files, dir || this.getCurrentDirectory(), isDir); }, /** @@ -1489,8 +1541,6 @@ if (etag){ // use etag as cache buster urlSpec.c = etag; - } else { - console.warn('OCA.Files.FileList.lazyLoadPreview(): missing etag argument'); } previewURL = self.generatePreviewUrl(urlSpec); @@ -1514,6 +1564,9 @@ img.src = previewURL; }, + /** + * @deprecated + */ setDirectoryPermissions: function(permissions) { var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; this.$el.find('#permissions').val(permissions); @@ -1610,7 +1663,7 @@ * fileData should be inserted, considering the current * sorting * - * @param {OCA.Files.FileInfo} fileData file info + * @param {OC.Files.FileInfo} fileData file info */ _findInsertionIndex: function(fileData) { var index = 0; @@ -1628,6 +1681,9 @@ move: function(fileNames, targetPath) { var self = this; var dir = this.getCurrentDirectory(); + if (dir.charAt(dir.length - 1) !== '/') { + dir += '/'; + } var target = OC.basename(targetPath); if (!_.isArray(fileNames)) { fileNames = [fileNames]; @@ -1635,46 +1691,42 @@ _.each(fileNames, function(fileName) { var $tr = self.findFileEl(fileName); self.showFileBusyState($tr, true); - // TODO: improve performance by sending all file names in a single call - $.post( - OC.filePath('files', 'ajax', 'move.php'), - { - dir: dir, - file: fileName, - target: targetPath - }, - function(result) { - if (result) { - if (result.status === 'success') { - // if still viewing the same directory - if (self.getCurrentDirectory() === dir) { - // recalculate folder size - var oldFile = self.findFileEl(target); - var newFile = self.findFileEl(fileName); - var oldSize = oldFile.data('size'); - var newSize = oldSize + newFile.data('size'); - oldFile.data('size', newSize); - oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize)); - - // TODO: also update entry in FileList.files - - self.remove(fileName); - } - } else { - OC.Notification.hide(); - if (result.status === 'error' && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } - else { - OC.Notification.showTemporary(t('files', 'Error moving file.')); - } - } + if (targetPath.charAt(targetPath.length - 1) !== '/') { + // make sure we move the files into the target dir, + // not overwrite it + targetPath = targetPath + '/'; + } + self.filesClient.move(dir + fileName, targetPath + fileName) + .done(function() { + // if still viewing the same directory + if (OC.joinPaths(self.getCurrentDirectory(), '/') === dir) { + // recalculate folder size + var oldFile = self.findFileEl(target); + var newFile = self.findFileEl(fileName); + var oldSize = oldFile.data('size'); + var newSize = oldSize + newFile.data('size'); + oldFile.data('size', newSize); + oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize)); + + // TODO: also update entry in FileList.files + self.remove(fileName); + } + }) + .fail(function(status) { + if (status === 412) { + // TODO: some day here we should invoke the conflict dialog + OC.Notification.showTemporary( + t('files', 'Could not move "{file}", target exists', {file: fileName}) + ); } else { - OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); + OC.Notification.showTemporary( + t('files', 'Could not move "{file}"', {file: fileName}) + ); } + }) + .always(function() { self.showFileBusyState($tr, false); - } - ); + }); }); }, @@ -1700,16 +1752,16 @@ * Triggers file rename input field for the given file name. * If the user enters a new name, the file will be renamed. * - * @param oldname file name of the file to rename + * @param oldName file name of the file to rename */ - rename: function(oldname) { + rename: function(oldName) { var self = this; var tr, td, input, form; - tr = this.findFileEl(oldname); + tr = this.findFileEl(oldName); var oldFileInfo = this.files[tr.index()]; tr.data('renaming',true); td = tr.children('td.filename'); - input = $('').val(oldname); + input = $('').val(oldName); form = $(''); form.append(input); td.children('a.name').hide(); @@ -1724,11 +1776,11 @@ input.selectRange(0, len); var checkInput = function () { var filename = input.val(); - if (filename !== oldname) { + if (filename !== oldName) { // Files.isFileNameValid(filename) throws an exception itself OCA.Files.Files.isFileNameValid(filename); if (self.inList(filename)) { - throw t('files', '{new_name} already exists', {new_name: filename}); + throw t('files', '{newName} already exists', {newName: filename}); } } return true; @@ -1741,6 +1793,14 @@ td.children('a.name').show(); } + function updateInList(fileInfo) { + tr.remove(); + tr = self.add(fileInfo, {updateSummary: false, silent: true}); + self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)})); + self._updateDetailsView(fileInfo.name); + } + + // TODO: too many nested blocks, move parts into functions form.submit(function(event) { event.stopPropagation(); event.preventDefault(); @@ -1753,7 +1813,7 @@ input.tooltip('hide'); form.remove(); - if (newName !== oldname) { + if (newName !== oldName) { checkInput(); // mark as loading (temp element) self.showFileBusyState(tr, true); @@ -1765,34 +1825,46 @@ td.find('a.name span.nametext').text(basename); td.children('a.name').show(); - $.ajax({ - url: OC.filePath('files','ajax','rename.php'), - data: { - dir : tr.attr('data-path') || self.getCurrentDirectory(), - newname: newName, - file: oldname - }, - success: function(result) { - var fileInfo; - if (!result || result.status === 'error') { - OC.dialogs.alert(result.data.message, t('files', 'Could not rename file')); - fileInfo = oldFileInfo; - if (result.data.code === 'sourcenotfound') { - self.remove(result.data.newname, {updateSummary: true}); - return; - } - } - else { - fileInfo = result.data; + var path = tr.attr('data-path') || self.getCurrentDirectory(); + self.filesClient.move(path + '/' + oldName, path + '/' + newName) + .done(function() { + var fileInfo = self.files.splice(tr.index(), 1)[0]; + fileInfo.name = newName; + updateInList(fileInfo); + }) + .fail(function(status) { + // TODO: 409 means current folder does not exist, redirect ? + if (status === 404) { + // source not found, so remove it from the list + OC.Notification.showTemporary( + t( + 'files', + 'Could not rename "{fileName}", it does not exist any more', + {fileName: oldName} + ) + ); + self.remove(newName, {updateSummary: true}); + return; + } else if (status === 412) { + // target exists + OC.Notification.showTemporary( + t( + 'files', + 'The name "{targetName}" is already used in the folder "{dir}". Please choose a different name.', + { + targetName: newName, + dir: self.getCurrentDirectory() + } + ) + ); + } else { + // restore the item to its previous state + OC.Notification.showTemporary( + t('files', 'Could not rename "{fileName}"', {fileName: oldName}) + ); } - // reinsert row - self.files.splice(tr.index(), 1); - tr.remove(); - tr = self.add(fileInfo, {updateSummary: false, silent: true}); - self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)})); - self._updateDetailsView(fileInfo.name, false); - } - }); + updateInList(oldFileInfo); + }); } else { // add back the old file info when cancelled self.files.splice(tr.index(), 1); @@ -1849,32 +1921,44 @@ var promise = deferred.promise(); OCA.Files.Files.isFileNameValid(name); - name = this.getUniqueName(name); if (this.lastAction) { this.lastAction(); } - $.post( - OC.generateUrl('/apps/files/ajax/newfile.php'), - { - dir: this.getCurrentDirectory(), - filename: name - }, - function(result) { - if (result.status === 'success') { - self.add(result.data, {animate: true, scrollTo: true}); - deferred.resolve(result.status, result.data); + name = this.getUniqueName(name); + var targetPath = this.getCurrentDirectory() + '/' + name; + + self.filesClient.putFileContents( + targetPath, + '', + { + contentType: 'text/plain', + overwrite: true + } + ) + .done(function() { + // TODO: error handling / conflicts + self.filesClient.getFileInfo(targetPath) + .then(function(status, data) { + self.add(data, {animate: true, scrollTo: true}); + deferred.resolve(status, data); + }) + .fail(function(status) { + OC.Notification.showTemporary(t('files', 'Could not create file "{file}"', {file: name})); + deferred.reject(status); + }); + }) + .fail(function(status) { + if (status === 412) { + OC.Notification.showTemporary( + t('files', 'Could not create file "{file}" because it already exists', {file: name}) + ); } else { - if (result.data && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } else { - OC.Notification.showTemporary(t('core', 'Could not create file')); - } - deferred.reject(result.status, result.data); + OC.Notification.showTemporary(t('files', 'Could not create file "{file}"', {file: name})); } - } - ); + deferred.reject(status); + }); return promise; }, @@ -1895,32 +1979,50 @@ var promise = deferred.promise(); OCA.Files.Files.isFileNameValid(name); - name = this.getUniqueName(name); if (this.lastAction) { this.lastAction(); } - $.post( - OC.generateUrl('/apps/files/ajax/newfolder.php'), - { - dir: this.getCurrentDirectory(), - foldername: name - }, - function(result) { - if (result.status === 'success') { - self.add(result.data, {animate: true, scrollTo: true}); - deferred.resolve(result.status, result.data); + name = this.getUniqueName(name); + var targetPath = this.getCurrentDirectory() + '/' + name; + + this.filesClient.createDirectory(targetPath) + .done(function(createStatus) { + self.filesClient.getFileInfo(targetPath) + .done(function(status, data) { + self.add(data, {animate: true, scrollTo: true}); + deferred.resolve(status, data); + }) + .fail(function() { + OC.Notification.showTemporary(t('files', 'Could not create folder "{dir}"', {dir: name})); + deferred.reject(createStatus); + }); + }) + .fail(function(createStatus) { + // method not allowed, folder might exist already + if (createStatus === 405) { + self.filesClient.getFileInfo(targetPath) + .done(function(status, data) { + // add it to the list, for completeness + self.add(data, {animate: true, scrollTo: true}); + OC.Notification.showTemporary( + t('files', 'Could not create folder "{dir}" because it already exists', {dir: name}) + ); + // still consider a failure + deferred.reject(createStatus, data); + }) + .fail(function() { + OC.Notification.showTemporary( + t('files', 'Could not create folder "{dir}"', {dir: name}) + ); + deferred.reject(status); + }); } else { - if (result.data && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } else { - OC.Notification.showTemporary(t('core', 'Could not create folder')); - } - deferred.reject(result.status); + OC.Notification.showTemporary(t('files', 'Could not create folder "{dir}"', {dir: name})); + deferred.reject(createStatus); } - } - ); + }); return promise; }, @@ -1981,76 +2083,59 @@ */ do_delete:function(files, dir) { var self = this; - var params; if (files && files.substr) { files=[files]; } + if (!files) { + // delete all files in directory + files = _.pluck(this.files, 'name'); + } if (files) { this.showFileBusyState(files, true); - for (var i=0; iview = $view; - $this->l10n = $l10n; - } - /** * Returns the app's navigation manager * * @return \OCP\INavigationManager */ public static function getNavigationManager() { + // TODO: move this into a service in the Application class if (self::$navigationManager === null) { self::$navigationManager = new \OC\NavigationManager(); } return self::$navigationManager; } - /** - * rename a file - * - * @param string $dir - * @param string $oldname - * @param string $newname - * @return array - */ - public function rename($dir, $oldname, $newname) { - $result = array( - 'success' => false, - 'data' => NULL - ); - - try { - // check if the new name is conform to file name restrictions - $this->view->verifyPath($dir, $newname); - } catch (\OCP\Files\InvalidPathException $ex) { - $result['data'] = array( - 'message' => $this->l10n->t($ex->getMessage()), - 'code' => 'invalidname', - ); - return $result; - } - - $normalizedOldPath = \OC\Files\Filesystem::normalizePath($dir . '/' . $oldname); - $normalizedNewPath = \OC\Files\Filesystem::normalizePath($dir . '/' . $newname); - - // rename to non-existing folder is denied - if (!$this->view->file_exists($normalizedOldPath)) { - $result['data'] = array( - 'message' => $this->l10n->t('%s could not be renamed as it has been deleted', array($oldname)), - 'code' => 'sourcenotfound', - 'oldname' => $oldname, - 'newname' => $newname, - ); - }else if (!$this->view->file_exists($dir)) { - $result['data'] = array('message' => (string)$this->l10n->t( - 'The target folder has been moved or deleted.', - array($dir)), - 'code' => 'targetnotfound' - ); - // rename to existing file is denied - } else if ($this->view->file_exists($normalizedNewPath)) { - - $result['data'] = array( - 'message' => $this->l10n->t( - "The name %s is already used in the folder %s. Please choose a different name.", - array($newname, $dir)) - ); - } else if ( - // rename to "." is denied - $newname !== '.' and - // THEN try to rename - $this->view->rename($normalizedOldPath, $normalizedNewPath) - ) { - // successful rename - $meta = $this->view->getFileInfo($normalizedNewPath); - $meta = \OCA\Files\Helper::populateTags(array($meta)); - $fileInfo = \OCA\Files\Helper::formatFileInfo(current($meta)); - $fileInfo['path'] = dirname($normalizedNewPath); - $result['success'] = true; - $result['data'] = $fileInfo; - } else { - // rename failed - $result['data'] = array( - 'message' => $this->l10n->t('%s could not be renamed', array($oldname)) - ); - } - return $result; - } - } diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index fb14cea731f..9a4e8d59786 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -139,9 +139,6 @@ class Helper { $entry['parentId'] = $i['parent']; $entry['mtime'] = $i['mtime'] * 1000; // only pick out the needed attributes - if (\OC::$server->getPreviewManager()->isAvailable($i)) { - $entry['isPreviewAvailable'] = true; - } $entry['name'] = $i->getName(); $entry['permissions'] = $i['permissions']; $entry['mimetype'] = $i['mimetype']; diff --git a/apps/files/tests/ajax_rename.php b/apps/files/tests/ajax_rename.php deleted file mode 100644 index 859c7042b89..00000000000 --- a/apps/files/tests/ajax_rename.php +++ /dev/null @@ -1,232 +0,0 @@ - - * @author Christopher Schäpers - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2015, 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 - * - */ - -class Test_OC_Files_App_Rename extends \Test\TestCase { - private static $user; - - /** - * @var PHPUnit_Framework_MockObject_MockObject - */ - private $viewMock; - - /** - * @var \OCA\Files\App - */ - private $files; - - protected function setUp() { - parent::setUp(); - - // mock OC_L10n - if (!self::$user) { - self::$user = uniqid(); - } - \OC_User::createUser(self::$user, 'password'); - $this->loginAsUser(self::$user); - - $l10nMock = $this->getMock('\OC_L10N', array('t'), array(), '', false); - $l10nMock->expects($this->any()) - ->method('t') - ->will($this->returnArgument(0)); - $viewMock = $this->getMock('\OC\Files\View', array('rename', 'normalizePath', 'getFileInfo', 'file_exists'), array(), '', false); - $viewMock->expects($this->any()) - ->method('normalizePath') - ->will($this->returnArgument(0)); - $viewMock->expects($this->any()) - ->method('rename') - ->will($this->returnValue(true)); - $this->viewMock = $viewMock; - $this->files = new \OCA\Files\App($viewMock, $l10nMock); - } - - protected function tearDown() { - $result = \OC_User::deleteUser(self::$user); - $this->assertTrue($result); - - $this->logout(); - parent::tearDown(); - } - - /** - * test rename of file/folder - */ - function testRenameFolder() { - $dir = '/'; - $oldname = 'oldname'; - $newname = 'newname'; - - $this->viewMock->expects($this->any()) - ->method('file_exists') - ->with($this->anything()) - ->will($this->returnValueMap(array( - array('/', true), - array('/oldname', true) - ))); - - - $this->viewMock->expects($this->any()) - ->method('getFileInfo') - ->will($this->returnValue(new \OC\Files\FileInfo( - '/new_name', - new \OC\Files\Storage\Local(array('datadir' => '/')), - '/', - array( - 'fileid' => 123, - 'type' => 'dir', - 'mimetype' => 'httpd/unix-directory', - 'mtime' => 0, - 'permissions' => 31, - 'size' => 18, - 'etag' => 'abcdef', - 'directory' => '/', - 'name' => 'new_name', - ), null))); - - $result = $this->files->rename($dir, $oldname, $newname); - - $this->assertTrue($result['success']); - $this->assertEquals(123, $result['data']['id']); - $this->assertEquals('new_name', $result['data']['name']); - $this->assertEquals(18, $result['data']['size']); - $this->assertEquals('httpd/unix-directory', $result['data']['mimetype']); - $this->assertEquals('abcdef', $result['data']['etag']); - $this->assertFalse(isset($result['data']['tags'])); - $this->assertEquals('/', $result['data']['path']); - } - - /** - * test rename of file with tag - */ - function testRenameFileWithTag() { - $taggerMock = $this->getMock('\OCP\ITags'); - $taggerMock->expects($this->any()) - ->method('getTagsForObjects') - ->with(array(123)) - ->will($this->returnValue(array(123 => array('tag1', 'tag2')))); - $tagManagerMock = $this->getMock('\OCP\ITagManager'); - $tagManagerMock->expects($this->any()) - ->method('load') - ->with('files') - ->will($this->returnValue($taggerMock)); - $oldTagManager = \OC::$server->query('TagManager'); - \OC::$server->registerService('TagManager', function ($c) use ($tagManagerMock) { - return $tagManagerMock; - }); - - $dir = '/'; - $oldname = 'oldname.txt'; - $newname = 'newname.txt'; - - $this->viewMock->expects($this->any()) - ->method('file_exists') - ->with($this->anything()) - ->will($this->returnValueMap(array( - array('/', true), - array('/oldname.txt', true) - ))); - - - $this->viewMock->expects($this->any()) - ->method('getFileInfo') - ->will($this->returnValue(new \OC\Files\FileInfo( - '/new_name.txt', - new \OC\Files\Storage\Local(array('datadir' => '/')), - '/', - array( - 'fileid' => 123, - 'type' => 'file', - 'mimetype' => 'text/plain', - 'mtime' => 0, - 'permissions' => 31, - 'size' => 18, - 'etag' => 'abcdef', - 'directory' => '/', - 'name' => 'new_name.txt', - ), null))); - - $result = $this->files->rename($dir, $oldname, $newname); - - $this->assertTrue($result['success']); - $this->assertEquals(123, $result['data']['id']); - $this->assertEquals('new_name.txt', $result['data']['name']); - $this->assertEquals(18, $result['data']['size']); - $this->assertEquals('text/plain', $result['data']['mimetype']); - $this->assertEquals('abcdef', $result['data']['etag']); - $this->assertEquals(array('tag1', 'tag2'), $result['data']['tags']); - $this->assertEquals('/', $result['data']['path']); - - \OC::$server->registerService('TagManager', function ($c) use ($oldTagManager) { - return $oldTagManager; - }); - } - - /** - * Test rename inside a folder that doesn't exist any more - */ - function testRenameInNonExistingFolder() { - $dir = '/unexist'; - $oldname = 'oldname'; - $newname = 'newname'; - - $this->viewMock->expects($this->at(0)) - ->method('file_exists') - ->with('/unexist/oldname') - ->will($this->returnValue(false)); - - $this->viewMock->expects($this->any()) - ->method('getFileInfo') - ->will($this->returnValue(array( - 'fileid' => 123, - 'type' => 'dir', - 'mimetype' => 'httpd/unix-directory', - 'size' => 18, - 'etag' => 'abcdef', - 'directory' => '/unexist', - 'name' => 'new_name', - ))); - - $result = $this->files->rename($dir, $oldname, $newname); - - $this->assertFalse($result['success']); - $this->assertEquals('sourcenotfound', $result['data']['code']); - } - - /** - * Test move to invalid name - */ - function testRenameToInvalidName() { - $dir = '/'; - $oldname = 'oldname'; - $newname = 'abc\\'; - - $result = $this->files->rename($dir, $oldname, $newname); - - $this->assertFalse($result['success']); - $this->assertEquals('File name contains at least one invalid character', $result['data']['message']); - $this->assertEquals('invalidname', $result['data']['code']); - } -} diff --git a/apps/files/tests/js/favoritesfilelistspec.js b/apps/files/tests/js/favoritesfilelistspec.js index 608ddaca18b..1c833d334e2 100644 --- a/apps/files/tests/js/favoritesfilelistspec.js +++ b/apps/files/tests/js/favoritesfilelistspec.js @@ -100,8 +100,7 @@ describe('OCA.Files.FavoritesFileList tests', function() { expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.find('a.name').attr('href')).toEqual( OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Fsomedir&files=test.txt' + '/remote.php/webdav/somedir/test.txt' ); expect($tr.find('.nametext').text().trim()).toEqual('test.txt'); }); diff --git a/apps/files/tests/js/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js index a49a5d4e2e0..8a0d6b01952 100644 --- a/apps/files/tests/js/fileUploadSpec.js +++ b/apps/files/tests/js/fileUploadSpec.js @@ -19,6 +19,8 @@ * */ +/* global FileList */ + describe('OC.Upload tests', function() { var $dummyUploader; var testFile; diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index d29164c5136..a905a4d969d 100644 --- a/apps/files/tests/js/fileactionsSpec.js +++ b/apps/files/tests/js/fileactionsSpec.js @@ -584,7 +584,7 @@ describe('OCA.Files.FileActions tests', function() { expect(busyStub.calledWith('testName.txt', true)).toEqual(true); expect(handleDownloadStub.calledOnce).toEqual(true); expect(handleDownloadStub.getCall(0).args[0]).toEqual( - OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=testName.txt' + OC.webroot + '/remote.php/webdav/subdir/testName.txt' ); busyStub.reset(); handleDownloadStub.yield(); diff --git a/apps/files/tests/js/fileactionsmenuSpec.js b/apps/files/tests/js/fileactionsmenuSpec.js index dee542458b6..747a746a602 100644 --- a/apps/files/tests/js/fileactionsmenuSpec.js +++ b/apps/files/tests/js/fileactionsmenuSpec.js @@ -237,8 +237,8 @@ describe('OCA.Files.FileActionsMenu tests', function() { expect(redirectStub.calledOnce).toEqual(true); expect(redirectStub.getCall(0).args[0]).toContain( OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Fsubdir&files=testName.txt'); + '/remote.php/webdav/subdir/testName.txt' + ); redirectStub.restore(); }); it('takes the file\'s path into account when clicking download', function() { @@ -269,8 +269,7 @@ describe('OCA.Files.FileActionsMenu tests', function() { expect(redirectStub.calledOnce).toEqual(true); expect(redirectStub.getCall(0).args[0]).toContain( - OC.webroot + '/index.php/apps/files/ajax/download.php' + - '?dir=%2Fanotherpath%2Fthere&files=testName.txt' + OC.webroot + '/remote.php/webdav/anotherpath/there/testName.txt' ); redirectStub.restore(); }); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 05e6fcc6122..9f7ad50bc60 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -20,8 +20,11 @@ */ describe('OCA.Files.FileList tests', function() { - var testFiles, alertStub, notificationStub, fileList, pageSizeStub; + var FileInfo = OC.Files.FileInfo; + var testFiles, testRoot, notificationStub, fileList, pageSizeStub; var bcResizeStub; + var filesClient; + var redirectStub; /** * Generate test file data @@ -38,21 +41,29 @@ describe('OCA.Files.FileList tests', function() { name += '0'; } name += i + '.txt'; - files.push({ + files.push(new FileInfo({ id: i, type: 'file', name: name, mimetype: 'text/plain', size: i * 2, etag: 'abc' - }); + })); } return files; } beforeEach(function() { - alertStub = sinon.stub(OC.dialogs, 'alert'); - notificationStub = sinon.stub(OC.Notification, 'show'); + filesClient = new OC.Files.Client({ + host: 'localhost', + port: 80, + // FIXME: uncomment after fixing the test OC.webroot + //root: OC.webroot + '/remote.php/webdav', + root: '/remote.php/webdav', + useHTTPS: false + }); + redirectStub = sinon.stub(OC, 'redirect'); + notificationStub = sinon.stub(OC.Notification, 'showTemporary'); // prevent resize algo to mess up breadcrumb order while // testing bcResizeStub = sinon.stub(OCA.Files.BreadCrumb.prototype, '_resize'); @@ -93,7 +104,17 @@ describe('OCA.Files.FileList tests', function() { '' ); - testFiles = [{ + testRoot = new FileInfo({ + // root entry + id: 99, + type: 'dir', + name: '/subdir', + mimetype: 'httpd/unix-directory', + size: 1200000, + etag: 'a0b0c0d0', + permissions: OC.PERMISSION_ALL + }); + testFiles = [new FileInfo({ id: 1, type: 'file', name: 'One.txt', @@ -102,7 +123,7 @@ describe('OCA.Files.FileList tests', function() { size: 12, etag: 'abc', permissions: OC.PERMISSION_ALL - }, { + }), new FileInfo({ id: 2, type: 'file', name: 'Two.jpg', @@ -111,7 +132,7 @@ describe('OCA.Files.FileList tests', function() { size: 12049, etag: 'def', permissions: OC.PERMISSION_ALL - }, { + }), new FileInfo({ id: 3, type: 'file', name: 'Three.pdf', @@ -120,7 +141,7 @@ describe('OCA.Files.FileList tests', function() { size: 58009, etag: '123', permissions: OC.PERMISSION_ALL - }, { + }), new FileInfo({ id: 4, type: 'dir', name: 'somedir', @@ -129,9 +150,11 @@ describe('OCA.Files.FileList tests', function() { size: 250, etag: '456', permissions: OC.PERMISSION_ALL - }]; + })]; pageSizeStub = sinon.stub(OCA.Files.FileList.prototype, 'pageSize').returns(20); - fileList = new OCA.Files.FileList($('#app-content-files')); + fileList = new OCA.Files.FileList($('#app-content-files'), { + filesClient: filesClient + }); }); afterEach(function() { testFiles = undefined; @@ -141,9 +164,9 @@ describe('OCA.Files.FileList tests', function() { fileList = undefined; notificationStub.restore(); - alertStub.restore(); bcResizeStub.restore(); pageSizeStub.restore(); + redirectStub.restore(); }); describe('Getters', function() { it('Returns the current directory', function() { @@ -166,15 +189,14 @@ describe('OCA.Files.FileList tests', function() { clock.restore(); }); it('generates file element with correct attributes when calling add() with file data', function() { - var fileData = { + var fileData = new FileInfo({ id: 18, - type: 'file', name: 'testName.txt', mimetype: 'text/plain', - size: '1234', + size: 1234, etag: 'a01234c', - mtime: '123456' - }; + mtime: 123456 + }); var $tr = fileList.add(fileData); expect($tr).toBeDefined(); @@ -188,7 +210,7 @@ describe('OCA.Files.FileList tests', function() { expect($tr.attr('data-mime')).toEqual('text/plain'); expect($tr.attr('data-mtime')).toEqual('123456'); expect($tr.find('a.name').attr('href')) - .toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=testName.txt'); + .toEqual(OC.webroot + '/remote.php/webdav/subdir/testName.txt'); expect($tr.find('.nametext').text().trim()).toEqual('testName.txt'); expect($tr.find('.filesize').text()).toEqual('1 kB'); @@ -196,15 +218,14 @@ describe('OCA.Files.FileList tests', function() { expect(fileList.findFileEl('testName.txt')[0]).toEqual($tr[0]); }); it('generates dir element with correct attributes when calling add() with dir data', function() { - var fileData = { + var fileData = new FileInfo({ id: 19, - type: 'dir', name: 'testFolder', mimetype: 'httpd/unix-directory', - size: '1234', + size: 1234, etag: 'a01234c', - mtime: '123456' - }; + mtime: 123456 + }); var $tr = fileList.add(fileData); expect($tr).toBeDefined(); @@ -297,7 +318,6 @@ describe('OCA.Files.FileList tests', function() { expect($tr.index()).toEqual(4); }); it('inserts files in a sorted manner when insert option is enabled', function() { - var $tr; for (var i = 0; i < testFiles.length; i++) { fileList.add(testFiles[i]); } @@ -423,28 +443,31 @@ describe('OCA.Files.FileList tests', function() { }); }); describe('Deleting files', function() { + var deferredDelete; + var deleteStub; + + beforeEach(function() { + deferredDelete = $.Deferred(); + deleteStub = sinon.stub(filesClient, 'remove').returns(deferredDelete.promise()); + }); + afterEach(function() { + deleteStub.restore(); + }); + function doDelete() { - var request, query; // note: normally called from FileActions fileList.do_delete(['One.txt', 'Two.jpg']); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php'); - - query = fakeServer.requests[0].requestBody; - expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir', files: '["One.txt","Two.jpg"]'}); + expect(deleteStub.calledTwice).toEqual(true); + expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); + expect(deleteStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg'); } it('calls delete.php, removes the deleted entries and updates summary', function() { var $summary; fileList.setFiles(testFiles); doDelete(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); + deferredDelete.resolve(200); expect(fileList.findFileEl('One.txt').length).toEqual(0); expect(fileList.findFileEl('Two.jpg').length).toEqual(0); @@ -482,11 +505,7 @@ describe('OCA.Files.FileList tests', function() { fileList.setFiles([testFiles[0], testFiles[1]]); doDelete(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); + deferredDelete.resolve(200); expect(fileList.$fileList.find('tr').length).toEqual(0); @@ -501,21 +520,41 @@ describe('OCA.Files.FileList tests', function() { fileList.setFiles(testFiles); doDelete(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'error', data: {message: 'WOOT'}}) - ); + deferredDelete.reject(403); // files are still in the list expect(fileList.findFileEl('One.txt').length).toEqual(1); expect(fileList.findFileEl('Two.jpg').length).toEqual(1); expect(fileList.$fileList.find('tr').length).toEqual(4); - expect(notificationStub.calledOnce).toEqual(true); + expect(notificationStub.calledTwice).toEqual(true); + }); + it('remove file from list if delete call returned 404 not found', function() { + fileList.setFiles(testFiles); + doDelete(); + + deferredDelete.reject(404); + + // files are still in the list + expect(fileList.findFileEl('One.txt').length).toEqual(0); + expect(fileList.findFileEl('Two.jpg').length).toEqual(0); + expect(fileList.$fileList.find('tr').length).toEqual(2); + + expect(notificationStub.notCalled).toEqual(true); }); }); describe('Renaming files', function() { + var deferredRename; + var renameStub; + + beforeEach(function() { + deferredRename = $.Deferred(); + renameStub = sinon.stub(filesClient, 'move').returns(deferredRename.promise()); + }); + afterEach(function() { + renameStub.restore(); + }); + function doCancelRename() { var $input; for (var i = 0; i < testFiles.length; i++) { @@ -530,10 +569,10 @@ describe('OCA.Files.FileList tests', function() { // trigger submit because triggering blur doesn't work in all browsers $input.closest('form').trigger('submit'); - expect(fakeServer.requests.length).toEqual(0); + expect(renameStub.notCalled).toEqual(true); } function doRename() { - var $input, request; + var $input; for (var i = 0; i < testFiles.length; i++) { var file = testFiles[i]; @@ -548,83 +587,61 @@ describe('OCA.Files.FileList tests', function() { // trigger submit because triggering blur doesn't work in all browsers $input.closest('form').trigger('submit'); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url.substr(0, request.url.indexOf('?'))).toEqual(OC.webroot + '/index.php/apps/files/ajax/rename.php'); - expect(OC.parseQueryString(request.url)).toEqual({'dir': '/some/subdir', newname: 'Tu_after_three.txt', file: 'One.txt'}); + expect(renameStub.calledOnce).toEqual(true); + expect(renameStub.getCall(0).args[0]).toEqual('/some/subdir/One.txt'); + expect(renameStub.getCall(0).args[1]).toEqual('/some/subdir/Tu_after_three.txt'); } it('Inserts renamed file entry at correct position if rename ajax call suceeded', function() { doRename(); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'Tu_after_three.txt', - type: 'file' - } - })); + deferredRename.resolve(201); // element stays renamed expect(fileList.findFileEl('One.txt').length).toEqual(0); expect(fileList.findFileEl('Tu_after_three.txt').length).toEqual(1); - expect(fileList.findFileEl('Tu_after_three.txt').index()).toEqual(2); // after Two.txt + expect(fileList.findFileEl('Tu_after_three.txt').index()).toEqual(2); // after Two.jpg - expect(alertStub.notCalled).toEqual(true); + expect(notificationStub.notCalled).toEqual(true); }); it('Reverts file entry if rename ajax call failed', function() { doRename(); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'error', - data: { - message: 'Something went wrong' - } - })); + deferredRename.reject(403); // element was reverted expect(fileList.findFileEl('One.txt').length).toEqual(1); expect(fileList.findFileEl('One.txt').index()).toEqual(1); // after somedir expect(fileList.findFileEl('Tu_after_three.txt').length).toEqual(0); - expect(alertStub.calledOnce).toEqual(true); + expect(notificationStub.calledOnce).toEqual(true); }); it('Correctly updates file link after rename', function() { var $tr; doRename(); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'Tu_after_three.txt' - } - })); + deferredRename.resolve(201); $tr = fileList.findFileEl('Tu_after_three.txt'); - expect($tr.find('a.name').attr('href')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=Tu_after_three.txt'); + expect($tr.find('a.name').attr('href')) + .toEqual(OC.webroot + '/remote.php/webdav/some/subdir/Tu_after_three.txt'); }); it('Triggers "fileActionsReady" event after rename', function() { var handler = sinon.stub(); fileList.$fileList.on('fileActionsReady', handler); doRename(); expect(handler.notCalled).toEqual(true); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'Tu_after_three.txt' - } - })); + + deferredRename.resolve(201); + expect(handler.calledOnce).toEqual(true); expect(fileList.$fileList.find('.test').length).toEqual(0); }); it('Leaves the summary alone when reinserting renamed element', function() { var $summary = $('#filestable .summary'); doRename(); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'Tu_after_three.txt' - } - })); + + deferredRename.resolve(201); + expect($summary.find('.info').text()).toEqual('1 folder and 3 files'); }); it('Leaves the summary alone when cancel renaming', function() { @@ -668,7 +685,7 @@ describe('OCA.Files.FileList tests', function() { // trigger submit does not send server request $input.closest('form').trigger('submit'); - expect(fakeServer.requests.length).toEqual(0); + expect(renameStub.notCalled).toEqual(true); // simulate escape key $input.trigger(new $.Event('keyup', {keyCode: 27})); @@ -694,12 +711,7 @@ describe('OCA.Files.FileList tests', function() { expect(OC.TestUtil.getImageUrl(fileList.findFileEl('Tu_after_three.txt').find('.thumbnail'))) .toEqual(OC.imagePath('core', 'loading.gif')); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'error', - data: { - message: 'Something went wrong' - } - })); + deferredRename.reject(409); expect(fileList.findFileEl('One.txt').length).toEqual(1); expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail'))) @@ -707,25 +719,27 @@ describe('OCA.Files.FileList tests', function() { }); }); describe('Moving files', function() { + var deferredMove; + var moveStub; + beforeEach(function() { + deferredMove = $.Deferred(); + moveStub = sinon.stub(filesClient, 'move').returns(deferredMove.promise()); + fileList.setFiles(testFiles); }); + afterEach(function() { + moveStub.restore(); + }); + it('Moves single file to target folder', function() { - var request; fileList.move('One.txt', '/somedir'); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); - expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'One.txt', target: '/somedir'}); + expect(moveStub.calledOnce).toEqual(true); + expect(moveStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); + expect(moveStub.getCall(0).args[1]).toEqual('/somedir/One.txt'); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'One.txt', - type: 'file' - } - })); + deferredMove.resolve(201); expect(fileList.findFileEl('One.txt').length).toEqual(0); @@ -736,39 +750,28 @@ describe('OCA.Files.FileList tests', function() { expect(notificationStub.notCalled).toEqual(true); }); it('Moves list of files to target folder', function() { - var request; + var deferredMove1 = $.Deferred(); + var deferredMove2 = $.Deferred(); + moveStub.onCall(0).returns(deferredMove1.promise()); + moveStub.onCall(1).returns(deferredMove2.promise()); + fileList.move(['One.txt', 'Two.jpg'], '/somedir'); - expect(fakeServer.requests.length).toEqual(2); - request = fakeServer.requests[0]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); - expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'One.txt', target: '/somedir'}); + expect(moveStub.calledTwice).toEqual(true); + expect(moveStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); + expect(moveStub.getCall(0).args[1]).toEqual('/somedir/One.txt'); + expect(moveStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg'); + expect(moveStub.getCall(1).args[1]).toEqual('/somedir/Two.jpg'); - request = fakeServer.requests[1]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); - expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'Two.jpg', target: '/somedir'}); - - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'One.txt', - type: 'file' - } - })); + deferredMove1.resolve(201); expect(fileList.findFileEl('One.txt').length).toEqual(0); - // folder size has increased + // folder size has increased during move expect(fileList.findFileEl('somedir').data('size')).toEqual(262); expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); - fakeServer.requests[1].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'success', - data: { - name: 'Two.jpg', - type: 'file' - } - })); + deferredMove2.resolve(201); expect(fileList.findFileEl('Two.jpg').length).toEqual(0); @@ -779,47 +782,31 @@ describe('OCA.Files.FileList tests', function() { expect(notificationStub.notCalled).toEqual(true); }); it('Shows notification if a file could not be moved', function() { - var request; fileList.move('One.txt', '/somedir'); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); - expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'One.txt', target: '/somedir'}); + expect(moveStub.calledOnce).toEqual(true); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'error', - data: { - message: 'Error while moving file' - } - })); + deferredMove.reject(409); expect(fileList.findFileEl('One.txt').length).toEqual(1); expect(notificationStub.calledOnce).toEqual(true); - expect(notificationStub.getCall(0).args[0]).toEqual('Error while moving file'); + expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"'); }); it('Restores thumbnail if a file could not be moved', function() { - var request; fileList.move('One.txt', '/somedir'); expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail'))) .toEqual(OC.imagePath('core', 'loading.gif')); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; + expect(moveStub.calledOnce).toEqual(true); - fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - status: 'error', - data: { - message: 'Error while moving file' - } - })); + deferredMove.reject(409); expect(fileList.findFileEl('One.txt').length).toEqual(1); expect(notificationStub.calledOnce).toEqual(true); - expect(notificationStub.getCall(0).args[0]).toEqual('Error while moving file'); + expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"'); expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail'))) .toEqual(OC.imagePath('core', 'filetypes/text.svg')); @@ -878,7 +865,7 @@ describe('OCA.Files.FileList tests', function() { name: 'testFile.txt', directory: '/current dir' }; - var $tr = fileList.add(fileData); + fileList.add(fileData); expect(fileList.findFileEl('testFile.txt').length).toEqual(1); }); it('triggers "fileActionsReady" event after update', function() { @@ -1143,69 +1130,85 @@ describe('OCA.Files.FileList tests', function() { afterEach(function() { previewLoadStub.restore(); }); - it('renders default icon for file when none provided and no preview is available', function() { + it('renders default file icon when none provided and no mime type is set', function() { var fileData = { - type: 'file', name: 'testFile.txt' }; var $tr = fileList.add(fileData); var $imgDiv = $tr.find('td.filename .thumbnail'); expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); - expect(previewLoadStub.notCalled).toEqual(true); + // tries to load preview + expect(previewLoadStub.calledOnce).toEqual(true); }); - it('renders default icon for dir when none provided and no preview is available', function() { + it('renders default icon for folder when none provided', function() { var fileData = { - type: 'dir', - name: 'test dir' + name: 'test dir', + mimetype: 'httpd/unix-directory' }; + var $tr = fileList.add(fileData); var $imgDiv = $tr.find('td.filename .thumbnail'); expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/folder.svg'); + // no preview since it's a directory expect(previewLoadStub.notCalled).toEqual(true); }); it('renders provided icon for file when provided', function() { - var fileData = { + var fileData = new FileInfo({ type: 'file', name: 'test file', icon: OC.webroot + '/core/img/filetypes/application-pdf.svg', mimetype: 'application/pdf' - }; + }); var $tr = fileList.add(fileData); var $imgDiv = $tr.find('td.filename .thumbnail'); expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/application-pdf.svg'); + // try loading preview + expect(previewLoadStub.calledOnce).toEqual(true); + }); + it('renders provided icon for file when provided', function() { + var fileData = new FileInfo({ + name: 'somefile.pdf', + icon: OC.webroot + '/core/img/filetypes/application-pdf.svg' + }); + + var $tr = fileList.add(fileData); + var $imgDiv = $tr.find('td.filename .thumbnail'); + expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/application-pdf.svg'); + // try loading preview + expect(previewLoadStub.calledOnce).toEqual(true); + }); + it('renders provided icon for folder when provided', function() { + var fileData = new FileInfo({ + name: 'some folder', + mimetype: 'httpd/unix-directory', + icon: OC.webroot + '/core/img/filetypes/folder-alt.svg' + }); + + var $tr = fileList.add(fileData); + var $imgDiv = $tr.find('td.filename .thumbnail'); + expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/folder-alt.svg'); + // do not load preview for folders expect(previewLoadStub.notCalled).toEqual(true); }); - it('renders preview when no icon was provided and preview is available', function() { + it('renders preview when no icon was provided', function() { var fileData = { type: 'file', - name: 'test file', - isPreviewAvailable: true + name: 'test file' }; var $tr = fileList.add(fileData); var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))) + .toEqual(OC.webroot + '/core/img/filetypes/file.svg'); expect(previewLoadStub.calledOnce).toEqual(true); // third argument is callback previewLoadStub.getCall(0).args[0].callback(OC.webroot + '/somepath.png'); expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/somepath.png'); }); - it('renders default file type icon when no icon was provided and no preview is available', function() { - var fileData = { - type: 'file', - name: 'test file', - isPreviewAvailable: false - }; - var $tr = fileList.add(fileData); - var $imgDiv = $tr.find('td.filename .thumbnail'); - expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); - expect(previewLoadStub.notCalled).toEqual(true); - }); it('does not render preview for directories', function() { var fileData = { type: 'dir', mimetype: 'httpd/unix-directory', - name: 'test dir', - isPreviewAvailable: true + name: 'test dir' }; var $tr = fileList.add(fileData); var $td = $tr.find('td.filename'); @@ -1217,7 +1220,6 @@ describe('OCA.Files.FileList tests', function() { type: 'dir', mimetype: 'httpd/unix-directory', name: 'test dir', - isPreviewAvailable: true, mountType: 'external-root' }; var $tr = fileList.add(fileData); @@ -1230,7 +1232,6 @@ describe('OCA.Files.FileList tests', function() { type: 'dir', mimetype: 'httpd/unix-directory', name: 'test dir', - isPreviewAvailable: true, mountType: 'external' }; var $tr = fileList.add(fileData); @@ -1278,75 +1279,47 @@ describe('OCA.Files.FileList tests', function() { }); }); describe('loading file list', function() { + var deferredList; + var getFolderContentsStub; + beforeEach(function() { - var data = { - status: 'success', - data: { - files: testFiles, - permissions: 31 - } - }; - fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2F(subdir|anothersubdir)/, [ - 200, { - "Content-Type": "application/json" - }, - JSON.stringify(data) - ]); + deferredList = $.Deferred(); + getFolderContentsStub = sinon.stub(filesClient, 'getFolderContents').returns(deferredList.promise()); + }); + afterEach(function() { + getFolderContentsStub.restore(); }); it('fetches file list from server and renders it when reload() is called', function() { fileList.reload(); - expect(fakeServer.requests.length).toEqual(1); - var url = fakeServer.requests[0].url; - var query = url.substr(url.indexOf('?') + 1); - expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir', sort: 'name', sortdirection: 'asc'}); - fakeServer.respond(); + expect(getFolderContentsStub.calledOnce).toEqual(true); + expect(getFolderContentsStub.calledWith('/subdir')).toEqual(true); + deferredList.resolve(200, [testRoot].concat(testFiles)); expect($('#fileList tr').length).toEqual(4); expect(fileList.findFileEl('One.txt').length).toEqual(1); }); it('switches dir and fetches file list when calling changeDirectory()', function() { fileList.changeDirectory('/anothersubdir'); expect(fileList.getCurrentDirectory()).toEqual('/anothersubdir'); - expect(fakeServer.requests.length).toEqual(1); - var url = fakeServer.requests[0].url; - var query = url.substr(url.indexOf('?') + 1); - expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir', sort: 'name', sortdirection: 'asc'}); - fakeServer.respond(); + expect(getFolderContentsStub.calledOnce).toEqual(true); + expect(getFolderContentsStub.calledWith('/anothersubdir')).toEqual(true); }); it('converts backslashes to slashes when calling changeDirectory()', function() { fileList.changeDirectory('/another\\subdir'); expect(fileList.getCurrentDirectory()).toEqual('/another/subdir'); }); it('switches to root dir when current directory does not exist', function() { - fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2funexist/, [ - 404, { - "Content-Type": "application/json" - }, - '' - ]); fileList.changeDirectory('/unexist'); - fakeServer.respond(); + deferredList.reject(404); expect(fileList.getCurrentDirectory()).toEqual('/'); }); it('switches to root dir when current directory is forbidden', function() { - fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2funexist/, [ - 403, { - "Content-Type": "application/json" - }, - '' - ]); fileList.changeDirectory('/unexist'); - fakeServer.respond(); + deferredList.reject(403); expect(fileList.getCurrentDirectory()).toEqual('/'); }); it('switches to root dir when current directory is unavailable', function() { - fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2funexist/, [ - 500, { - "Content-Type": "application/json" - }, - '' - ]); fileList.changeDirectory('/unexist'); - fakeServer.respond(); + deferredList.reject(500); expect(fileList.getCurrentDirectory()).toEqual('/'); }); it('shows mask before loading file list then hides it at the end', function() { @@ -1355,7 +1328,7 @@ describe('OCA.Files.FileList tests', function() { fileList.changeDirectory('/anothersubdir'); expect(showMaskStub.calledOnce).toEqual(true); expect(hideMaskStub.calledOnce).toEqual(false); - fakeServer.respond(); + deferredList.resolve(200, [testRoot].concat(testFiles)); expect(showMaskStub.calledOnce).toEqual(true); expect(hideMaskStub.calledOnce).toEqual(true); showMaskStub.restore(); @@ -1365,6 +1338,7 @@ describe('OCA.Files.FileList tests', function() { var handler = sinon.stub(); $('#app-content-files').on('changeDirectory', handler); fileList.changeDirectory('/somedir'); + deferredList.resolve(200, [testRoot].concat(testFiles)); expect(handler.calledOnce).toEqual(true); expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); }); @@ -1375,31 +1349,27 @@ describe('OCA.Files.FileList tests', function() { it('refreshes breadcrumb after update', function() { var setDirSpy = sinon.spy(fileList.breadcrumb, 'setDirectory'); fileList.changeDirectory('/anothersubdir'); - fakeServer.respond(); + deferredList.resolve(200, [testRoot].concat(testFiles)); expect(fileList.breadcrumb.setDirectory.calledOnce).toEqual(true); expect(fileList.breadcrumb.setDirectory.calledWith('/anothersubdir')).toEqual(true); setDirSpy.restore(); + getFolderContentsStub.restore(); }); }); describe('breadcrumb events', function() { + var deferredList; + var getFolderContentsStub; + beforeEach(function() { - var data = { - status: 'success', - data: { - files: testFiles, - permissions: 31 - } - }; - fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2Fsubdir/, [ - 200, { - "Content-Type": "application/json" - }, - JSON.stringify(data) - ]); + deferredList = $.Deferred(); + getFolderContentsStub = sinon.stub(filesClient, 'getFolderContents').returns(deferredList.promise()); + }); + afterEach(function() { + getFolderContentsStub.restore(); }); it('clicking on root breadcrumb changes directory to root', function() { fileList.changeDirectory('/subdir/two/three with space/four/five'); - fakeServer.respond(); + deferredList.resolve(200, [testRoot].concat(testFiles)); var changeDirStub = sinon.stub(fileList, 'changeDirectory'); fileList.breadcrumb.$el.find('.crumb:eq(0)').trigger({type: 'click', which: 1}); @@ -1409,7 +1379,7 @@ describe('OCA.Files.FileList tests', function() { }); it('clicking on breadcrumb changes directory', function() { fileList.changeDirectory('/subdir/two/three with space/four/five'); - fakeServer.respond(); + deferredList.resolve(200, [testRoot].concat(testFiles)); var changeDirStub = sinon.stub(fileList, 'changeDirectory'); fileList.breadcrumb.$el.find('.crumb:eq(3)').trigger({type: 'click', which: 1}); @@ -1418,9 +1388,10 @@ describe('OCA.Files.FileList tests', function() { changeDirStub.restore(); }); it('dropping files on breadcrumb calls move operation', function() { - var request, query, testDir = '/subdir/two/three with space/four/five'; + var testDir = '/subdir/two/three with space/four/five'; + var moveStub = sinon.stub(filesClient, 'move').returns($.Deferred().promise()); fileList.changeDirectory(testDir); - fakeServer.respond(); + deferredList.resolve(200, [testRoot].concat(testFiles)); var $crumb = fileList.breadcrumb.$el.find('.crumb:eq(3)'); // no idea what this is but is required by the handler var ui = { @@ -1436,33 +1407,18 @@ describe('OCA.Files.FileList tests', function() { // simulate drop event fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui); - // will trigger two calls to move.php (first one was previous list.php) - expect(fakeServer.requests.length).toEqual(3); - - request = fakeServer.requests[1]; - expect(request.method).toEqual('POST'); - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); - query = OC.parseQueryString(request.requestBody); - expect(query).toEqual({ - target: '/subdir/two/three with space', - dir: testDir, - file: 'One.txt' - }); - - request = fakeServer.requests[2]; - expect(request.method).toEqual('POST'); - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); - query = OC.parseQueryString(request.requestBody); - expect(query).toEqual({ - target: '/subdir/two/three with space', - dir: testDir, - file: 'Two.jpg' - }); + expect(moveStub.callCount).toEqual(2); + expect(moveStub.getCall(0).args[0]).toEqual(testDir + '/One.txt'); + expect(moveStub.getCall(0).args[1]).toEqual('/subdir/two/three with space/One.txt'); + expect(moveStub.getCall(1).args[0]).toEqual(testDir + '/Two.jpg'); + expect(moveStub.getCall(1).args[1]).toEqual('/subdir/two/three with space/Two.jpg'); + moveStub.restore(); }); it('dropping files on same dir breadcrumb does nothing', function() { var testDir = '/subdir/two/three with space/four/five'; + var moveStub = sinon.stub(filesClient, 'move').returns($.Deferred().promise()); fileList.changeDirectory(testDir); - fakeServer.respond(); + deferredList.resolve(200, [testRoot].concat(testFiles)); var $crumb = fileList.breadcrumb.$el.find('.crumb:last'); // no idea what this is but is required by the handler var ui = { @@ -1479,21 +1435,26 @@ describe('OCA.Files.FileList tests', function() { fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui); // no extra server request - expect(fakeServer.requests.length).toEqual(1); + expect(moveStub.notCalled).toEqual(true); }); }); describe('Download Url', function() { it('returns correct download URL for single files', function() { - expect(fileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=some%20file.txt'); - expect(fileList.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fanotherpath%2Fabc&files=some%20file.txt'); + expect(fileList.getDownloadUrl('some file.txt')) + .toEqual(OC.webroot + '/remote.php/webdav/subdir/some%20file.txt'); + expect(fileList.getDownloadUrl('some file.txt', '/anotherpath/abc')) + .toEqual(OC.webroot + '/remote.php/webdav/anotherpath/abc/some%20file.txt'); $('#dir').val('/'); - expect(fileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=some%20file.txt'); + expect(fileList.getDownloadUrl('some file.txt')) + .toEqual(OC.webroot + '/remote.php/webdav/some%20file.txt'); }); it('returns correct download URL for multiple files', function() { - expect(fileList.getDownloadUrl(['a b c.txt', 'd e f.txt'])).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22a%20b%20c.txt%22%2C%22d%20e%20f.txt%22%5D'); + expect(fileList.getDownloadUrl(['a b c.txt', 'd e f.txt'])) + .toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22a%20b%20c.txt%22%2C%22d%20e%20f.txt%22%5D'); }); it('returns the correct ajax URL', function() { - expect(fileList.getAjaxUrl('test', {a:1, b:'x y'})).toEqual(OC.webroot + '/index.php/apps/files/ajax/test.php?a=1&b=x%20y'); + expect(fileList.getAjaxUrl('test', {a:1, b:'x y'})) + .toEqual(OC.webroot + '/index.php/apps/files/ajax/test.php?a=1&b=x%20y'); }); }); describe('File selection', function() { @@ -1672,24 +1633,17 @@ describe('OCA.Files.FileList tests', function() { }); it('Selection is cleared when switching dirs', function() { $('.select-all').click(); - var data = { - status: 'success', - data: { - files: testFiles, - permissions: 31 - } - }; - fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php/, [ - 200, { - "Content-Type": "application/json" - }, - JSON.stringify(data) - ] - ); + var deferredList = $.Deferred(); + var getFolderContentsStub = sinon.stub(filesClient, 'getFolderContents').returns(deferredList.promise()); + fileList.changeDirectory('/'); - fakeServer.respond(); + + deferredList.resolve(200, [testRoot].concat(testFiles)); + expect($('.select-all').prop('checked')).toEqual(false); expect(_.pluck(fileList.getSelectedFiles(), 'name')).toEqual([]); + + getFolderContentsStub.restore(); }); it('getSelectedFiles returns the selected files even when they are on the next page', function() { var selectedFiles; @@ -1796,6 +1750,12 @@ describe('OCA.Files.FileList tests', function() { etag: '456', permissions: OC.PERMISSION_ALL }); + expect(files[0].id).toEqual(1); + expect(files[0].name).toEqual('One.txt'); + expect(files[1].id).toEqual(3); + expect(files[1].name).toEqual('Three.pdf'); + expect(files[2].id).toEqual(4); + expect(files[2].name).toEqual('somedir'); }); it('Removing a file removes it from the selection', function() { fileList.remove('Three.pdf'); @@ -1824,7 +1784,6 @@ describe('OCA.Files.FileList tests', function() { }); describe('Download', function() { it('Opens download URL when clicking "Download"', function() { - var redirectStub = sinon.stub(OC, 'redirect'); $('.selectedActions .download').click(); expect(redirectStub.calledOnce).toEqual(true); expect(redirectStub.getCall(0).args[0]).toContain(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22One.txt%22%2C%22Three.pdf%22%2C%22somedir%22%5D'); @@ -1833,54 +1792,53 @@ describe('OCA.Files.FileList tests', function() { it('Downloads root folder when all selected in root folder', function() { $('#dir').val('/'); $('.select-all').click(); - var redirectStub = sinon.stub(OC, 'redirect'); $('.selectedActions .download').click(); expect(redirectStub.calledOnce).toEqual(true); expect(redirectStub.getCall(0).args[0]).toContain(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files='); - redirectStub.restore(); }); it('Downloads parent folder when all selected in subfolder', function() { $('.select-all').click(); - var redirectStub = sinon.stub(OC, 'redirect'); $('.selectedActions .download').click(); expect(redirectStub.calledOnce).toEqual(true); expect(redirectStub.getCall(0).args[0]).toContain(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=subdir'); - redirectStub.restore(); }); }); describe('Delete', function() { + var deleteStub, deferredDelete; + beforeEach(function() { + deferredDelete = $.Deferred(); + deleteStub = sinon.stub(filesClient, 'remove').returns(deferredDelete.promise()); + }); + afterEach(function() { + deleteStub.restore(); + }); it('Deletes selected files when "Delete" clicked', function() { - var request; $('.selectedActions .delete-selected').click(); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php'); - expect(OC.parseQueryString(request.requestBody)) - .toEqual({'dir': '/subdir', files: '["One.txt","Three.pdf","somedir"]'}); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); + + expect(deleteStub.callCount).toEqual(3); + expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); + expect(deleteStub.getCall(1).args[0]).toEqual('/subdir/Three.pdf'); + expect(deleteStub.getCall(2).args[0]).toEqual('/subdir/somedir'); + + deferredDelete.resolve(204); + expect(fileList.findFileEl('One.txt').length).toEqual(0); expect(fileList.findFileEl('Three.pdf').length).toEqual(0); expect(fileList.findFileEl('somedir').length).toEqual(0); expect(fileList.findFileEl('Two.jpg').length).toEqual(1); }); it('Deletes all files when all selected when "Delete" clicked', function() { - var request; $('.select-all').click(); $('.selectedActions .delete-selected').click(); - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php'); - expect(OC.parseQueryString(request.requestBody)) - .toEqual({'dir': '/subdir', allfiles: 'true'}); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); + + expect(deleteStub.callCount).toEqual(4); + expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); + expect(deleteStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg'); + expect(deleteStub.getCall(2).args[0]).toEqual('/subdir/Three.pdf'); + expect(deleteStub.getCall(3).args[0]).toEqual('/subdir/somedir'); + + deferredDelete.resolve(204); + expect(fileList.isEmpty).toEqual(true); }); }); @@ -2118,30 +2076,6 @@ describe('OCA.Files.FileList tests', function() { }); }); describe('Sorting files', function() { - it('Sorts by name by default', function() { - fileList.reload(); - expect(fakeServer.requests.length).toEqual(1); - var url = fakeServer.requests[0].url; - var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1)); - expect(query.sort).toEqual('name'); - expect(query.sortdirection).toEqual('asc'); - }); - it('Reloads file list with a different sort when clicking on column header of unsorted column', function() { - fileList.$el.find('.column-size .columntitle').click(); - expect(fakeServer.requests.length).toEqual(1); - var url = fakeServer.requests[0].url; - var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1)); - expect(query.sort).toEqual('size'); - expect(query.sortdirection).toEqual('desc'); - }); - it('Toggles sort direction when clicking on already sorted column', function() { - fileList.$el.find('.column-name .columntitle').click(); - expect(fakeServer.requests.length).toEqual(1); - var url = fakeServer.requests[0].url; - var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1)); - expect(query.sort).toEqual('name'); - expect(query.sortdirection).toEqual('desc'); - }); it('Toggles the sort indicator when clicking on a column header', function() { var ASC_CLASS = fileList.SORT_INDICATOR_ASC_CLASS; var DESC_CLASS = fileList.SORT_INDICATOR_DESC_CLASS; @@ -2191,28 +2125,15 @@ describe('OCA.Files.FileList tests', function() { it('Uses correct sort comparator when inserting files', function() { testFiles.sort(OCA.Files.FileList.Comparators.size); testFiles.reverse(); //default is descending - // this will make it reload the testFiles with the correct sorting + fileList.setFiles(testFiles); fileList.$el.find('.column-size .columntitle').click(); - expect(fakeServer.requests.length).toEqual(1); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - status: 'success', - data: { - files: testFiles, - permissions: 31 - } - }) - ); - var newFileData = { + var newFileData = new FileInfo({ id: 999, - type: 'file', name: 'new file.txt', mimetype: 'text/plain', size: 40001, etag: '999' - }; + }); fileList.add(newFileData); expect(fileList.findFileEl('Three.pdf').index()).toEqual(0); expect(fileList.findFileEl('new file.txt').index()).toEqual(1); @@ -2224,41 +2145,18 @@ describe('OCA.Files.FileList tests', function() { }); it('Uses correct reversed sort comparator when inserting files', function() { testFiles.sort(OCA.Files.FileList.Comparators.size); - // this will make it reload the testFiles with the correct sorting + fileList.setFiles(testFiles); fileList.$el.find('.column-size .columntitle').click(); - expect(fakeServer.requests.length).toEqual(1); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - status: 'success', - data: { - files: testFiles, - permissions: 31 - } - }) - ); + // reverse sort fileList.$el.find('.column-size .columntitle').click(); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - status: 'success', - data: { - files: testFiles, - permissions: 31 - } - }) - ); - var newFileData = { + var newFileData = new FileInfo({ id: 999, - type: 'file', name: 'new file.txt', mimetype: 'text/plain', size: 40001, etag: '999' - }; + }); fileList.add(newFileData); expect(fileList.findFileEl('One.txt').index()).toEqual(0); expect(fileList.findFileEl('somedir').index()).toEqual(1); @@ -2290,87 +2188,96 @@ describe('OCA.Files.FileList tests', function() { }); describe('create file', function() { var deferredCreate; + var deferredInfo; + var createStub; + var getFileInfoStub; beforeEach(function() { deferredCreate = $.Deferred(); + deferredInfo = $.Deferred(); + createStub = sinon.stub(filesClient, 'putFileContents') + .returns(deferredCreate.promise()); + getFileInfoStub = sinon.stub(filesClient, 'getFileInfo') + .returns(deferredInfo.promise()); + }); + afterEach(function() { + createStub.restore(); + getFileInfoStub.restore(); }); it('creates file with given name and adds it to the list', function() { - var deferred = fileList.createFile('test file.txt'); - var successStub = sinon.stub(); - var failureStub = sinon.stub(); + fileList.createFile('test.txt'); - deferred.done(successStub); - deferred.fail(failureStub); + expect(createStub.calledOnce).toEqual(true); + expect(createStub.getCall(0).args[0]).toEqual('/subdir/test.txt'); + expect(createStub.getCall(0).args[2]).toEqual({ + contentType: 'text/plain', + overwrite: true + }); - expect(fakeServer.requests.length).toEqual(1); - expect(fakeServer.requests[0].url).toEqual(OC.generateUrl('/apps/files/ajax/newfile.php')); + deferredCreate.resolve(200); - var query = fakeServer.requests[0].requestBody; - expect(OC.parseQueryString(query)).toEqual({ - dir: '/subdir', - filename: 'test file.txt' - }); + expect(getFileInfoStub.calledOnce).toEqual(true); + expect(getFileInfoStub.getCall(0).args[0]).toEqual('/subdir/test.txt'); - fakeServer.requests[0].respond( + deferredInfo.resolve( 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - status: 'success', - data: { - path: '/subdir', - name: 'test file.txt', - mimetype: 'text/plain' - } + new FileInfo({ + path: '/subdir', + name: 'test.txt', + mimetype: 'text/plain' }) ); - var $tr = fileList.findFileEl('test file.txt'); + var $tr = fileList.findFileEl('test.txt'); expect($tr.length).toEqual(1); expect($tr.attr('data-mime')).toEqual('text/plain'); - - expect(successStub.calledOnce).toEqual(true); - expect(failureStub.notCalled).toEqual(true); }); // TODO: error cases // TODO: unique name cases }); - describe('create directory', function() { - it('creates directory with given name and adds it to the list', function() { - var deferred = fileList.createDirectory('test directory'); - var successStub = sinon.stub(); - var failureStub = sinon.stub(); - - deferred.done(successStub); - deferred.fail(failureStub); - - expect(fakeServer.requests.length).toEqual(1); - expect(fakeServer.requests[0].url).toEqual(OC.generateUrl('/apps/files/ajax/newfolder.php')); - var query = fakeServer.requests[0].requestBody; - expect(OC.parseQueryString(query)).toEqual({ - dir: '/subdir', - foldername: 'test directory' - }); + describe('create folder', function() { + var deferredCreate; + var deferredInfo; + var createStub; + var getFileInfoStub; + + beforeEach(function() { + deferredCreate = $.Deferred(); + deferredInfo = $.Deferred(); + createStub = sinon.stub(filesClient, 'createDirectory') + .returns(deferredCreate.promise()); + getFileInfoStub = sinon.stub(filesClient, 'getFileInfo') + .returns(deferredInfo.promise()); + }); + afterEach(function() { + createStub.restore(); + getFileInfoStub.restore(); + }); + + it('creates folder with given name and adds it to the list', function() { + fileList.createDirectory('sub dir'); + + expect(createStub.calledOnce).toEqual(true); + expect(createStub.getCall(0).args[0]).toEqual('/subdir/sub dir'); - fakeServer.requests[0].respond( + deferredCreate.resolve(200); + + expect(getFileInfoStub.calledOnce).toEqual(true); + expect(getFileInfoStub.getCall(0).args[0]).toEqual('/subdir/sub dir'); + + deferredInfo.resolve( 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - status: 'success', - data: { - path: '/subdir', - name: 'test directory', - mimetype: 'httpd/unix-directory' - } + new FileInfo({ + path: '/subdir', + name: 'sub dir', + mimetype: 'httpd/unix-directory' }) ); - var $tr = fileList.findFileEl('test directory'); + var $tr = fileList.findFileEl('sub dir'); expect($tr.length).toEqual(1); expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); - - expect(successStub.calledOnce).toEqual(true); - expect(failureStub.notCalled).toEqual(true); }); // TODO: error cases // TODO: unique name cases @@ -2481,14 +2388,14 @@ describe('OCA.Files.FileList tests', function() { expect(ev.result).not.toEqual(false); }); it('drop on a folder row inside the table triggers upload to target folder', function() { - var ev, formData; + var ev; ev = dropOn(fileList.findFileEl('somedir').find('td:eq(2)'), uploadData); expect(ev.result).not.toEqual(false); expect(uploadData.targetDir).toEqual('/subdir/somedir'); }); it('drop on a breadcrumb inside the table triggers upload to target folder', function() { - var ev, formData; + var ev; fileList.changeDirectory('a/b/c/d'); ev = dropOn(fileList.$el.find('.crumb:eq(2)'), uploadData); @@ -2497,32 +2404,50 @@ describe('OCA.Files.FileList tests', function() { }); }); }); - describe('Handeling errors', function () { - var redirectStub; + describe('Handling errors', function () { + var deferredList; + var getFolderContentsStub; - beforeEach(function () { - redirectStub = sinon.stub(OC, 'redirect'); - - fileList = new OCA.Files.FileList($('#app-content-files')); + beforeEach(function() { + deferredList = $.Deferred(); + getFolderContentsStub = + sinon.stub(filesClient, 'getFolderContents'); + getFolderContentsStub.onCall(0).returns(deferredList.promise()); + getFolderContentsStub.onCall(1).returns($.Deferred().promise()); + fileList.reload(); }); - afterEach(function () { + afterEach(function() { + getFolderContentsStub.restore(); fileList = undefined; + }); + it('redirects to files app in case of auth error', function () { + deferredList.reject(401, 'Authentication error'); - redirectStub.restore(); + expect(redirectStub.calledOnce).toEqual(true); + expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files'); + expect(getFolderContentsStub.calledOnce).toEqual(true); }); - it('reloads the page on authentication errors', function () { - fileList.reload(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - status: 'error', - data: { - 'error': 'authentication_error' - } - }) - ); - expect(redirectStub.calledWith(OC.generateUrl('apps/files'))).toEqual(true); + it('redirects to root folder in case of forbidden access', function () { + deferredList.reject(403); + + expect(fileList.getCurrentDirectory()).toEqual('/'); + expect(getFolderContentsStub.calledTwice).toEqual(true); + }); + it('redirects to root folder and shows notification in case of internal server error', function () { + expect(notificationStub.notCalled).toEqual(true); + deferredList.reject(500); + + expect(fileList.getCurrentDirectory()).toEqual('/'); + expect(getFolderContentsStub.calledTwice).toEqual(true); + expect(notificationStub.calledOnce).toEqual(true); + }); + it('redirects to root folder and shows notification in case of storage not available', function () { + expect(notificationStub.notCalled).toEqual(true); + deferredList.reject(503, 'Storage not available'); + + expect(fileList.getCurrentDirectory()).toEqual('/'); + expect(getFolderContentsStub.calledTwice).toEqual(true); + expect(notificationStub.calledOnce).toEqual(true); }); }); describe('showFileBusyState', function() { diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index 30e6675c155..b7627d59fdf 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -76,11 +76,11 @@ describe('OCA.Files.Files tests', function() { describe('getDownloadUrl', function() { it('returns the ajax download URL when filename and dir specified', function() { var url = Files.getDownloadUrl('test file.txt', '/subdir'); - expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20file.txt'); + expect(url).toEqual(OC.webroot + '/remote.php/webdav/subdir/test%20file.txt'); }); - it('returns the ajax download URL when filename and root dir specific', function() { + it('returns the webdav download URL when filename and root dir specified', function() { var url = Files.getDownloadUrl('test file.txt', '/'); - expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=test%20file.txt'); + expect(url).toEqual(OC.webroot + '/remote.php/webdav/test%20file.txt'); }); it('returns the ajax download URL when multiple files specified', function() { var url = Files.getDownloadUrl(['test file.txt', 'abc.txt'], '/subdir'); diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index 68bfd63ec89..a799d4a94c2 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -231,6 +231,7 @@ files = _.chain(files) // convert share data to file data .map(function(share) { + // TODO: use OC.Files.FileInfo var file = { id: share.file_source, icon: OC.MimeType.getIconUrl(share.mimetype), @@ -242,9 +243,6 @@ } else { file.type = 'file'; - if (share.isPreviewAvailable) { - file.isPreviewAvailable = true; - } } file.share = { id: share.id, diff --git a/apps/files_sharing/tests/js/sharedfilelistSpec.js b/apps/files_sharing/tests/js/sharedfilelistSpec.js index b4b6ac4954a..fdc9de49c17 100644 --- a/apps/files_sharing/tests/js/sharedfilelistSpec.js +++ b/apps/files_sharing/tests/js/sharedfilelistSpec.js @@ -166,8 +166,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-id')).toEqual('7'); expect($tr.find('a.name').attr('href')).toEqual( OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Flocal%20path&files=local%20name.txt' + '/remote.php/webdav/local%20path/local%20name.txt' ); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); @@ -185,8 +184,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-id')).toEqual('8'); expect($tr.find('a.name').attr('href')).toEqual( OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2F&files=b.txt' + '/remote.php/webdav/b.txt' ); expect($tr.find('.nametext').text().trim()).toEqual('b.txt'); }); @@ -338,8 +336,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-id')).toEqual('7'); expect($tr.find('a.name').attr('href')).toEqual( OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Flocal%20path&files=local%20name.txt' + '/remote.php/webdav/local%20path/local%20name.txt' ); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); }); @@ -429,9 +426,8 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-owner')).not.toBeDefined(); expect($tr.attr('data-share-id')).toEqual('7'); expect($tr.find('a.name').attr('href')).toEqual( - OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Flocal%20path&files=local%20name.txt'); + OC.webroot + '/remote.php/webdav/local%20path/local%20name.txt' + ); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); }); @@ -498,9 +494,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-owner')).not.toBeDefined(); expect($tr.attr('data-share-id')).toEqual('7,8,9'); expect($tr.find('a.name').attr('href')).toEqual( - OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Flocal%20path&files=local%20name.txt' + OC.webroot + '/remote.php/webdav/local%20path/local%20name.txt' ); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); }); @@ -592,9 +586,8 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-owner')).not.toBeDefined(); expect($tr.attr('data-share-id')).toEqual('7'); expect($tr.find('a.name').attr('href')).toEqual( - OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Flocal%20path&files=local%20name.txt'); + OC.webroot + '/remote.php/webdav/local%20path/local%20name.txt' + ); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); }); @@ -634,8 +627,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-share-id')).toEqual('7'); expect($tr.find('a.name').attr('href')).toEqual( OC.webroot + - '/index.php/apps/files/ajax/download.php' + - '?dir=%2Flocal%20path&files=local%20name.txt'); + '/remote.php/webdav/local%20path/local%20name.txt'); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); }); diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js index 6b624e333a0..5812aff82f7 100644 --- a/apps/files_trashbin/js/filelist.js +++ b/apps/files_trashbin/js/filelist.js @@ -283,7 +283,77 @@ isSelectedDeletable: function() { return true; - } + }, + + /** + * Reloads the file list using ajax call + * + * @return ajax call object + */ + reload: function() { + this._selectedFiles = {}; + this._selectionSummary.clear(); + this.$el.find('.select-all').prop('checked', false); + this.showMask(); + if (this._reloadCall) { + this._reloadCall.abort(); + } + this._reloadCall = $.ajax({ + url: this.getAjaxUrl('list'), + data: { + dir : this.getCurrentDirectory(), + sort: this._sort, + sortdirection: this._sortDirection + } + }); + var callBack = this.reloadCallback.bind(this); + return this._reloadCall.then(callBack, callBack); + }, + reloadCallback: function(result) { + delete this._reloadCall; + this.hideMask(); + + if (!result || result.status === 'error') { + // if the error is not related to folder we're trying to load, reload the page to handle logout etc + if (result.data.error === 'authentication_error' || + result.data.error === 'token_expired' || + result.data.error === 'application_not_enabled' + ) { + OC.redirect(OC.generateUrl('apps/files')); + } + OC.Notification.show(result.data.message); + return false; + } + + // Firewall Blocked request? + if (result.status === 403) { + // Go home + this.changeDirectory('/'); + OC.Notification.show(t('files', 'This operation is forbidden')); + return false; + } + + // Did share service die or something else fail? + if (result.status === 500) { + // Go home + this.changeDirectory('/'); + OC.Notification.show(t('files', 'This directory is unavailable, please check the logs or contact the administrator')); + return false; + } + + if (result.status === 404) { + // go back home + this.changeDirectory('/'); + return false; + } + // aborted ? + if (result.status === 0){ + return true; + } + + this.setFiles(result.data.files); + return true; + }, }); diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index 4448b813021..fe93d0ea657 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -759,7 +759,7 @@ var OCdialogs = { filename: entry.name, date: OC.Util.relativeModifiedDate(entry.mtime) }); - if (entry.isPreviewAvailable) { + if (entry.type === 'file') { var urlSpec = { file: dir + '/' + entry.name }; -- GitLab From f20232d4bd3e78c4ea980aa03849c3f9bcf5b893 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 13 Jul 2015 17:41:20 +0200 Subject: [PATCH 126/344] Make public link share page work with Webdav and add operations The public page now uses the public.php/webdav endpoint. Also enabled more file operations like rename, move, delete and create folder from the public page, which are now all possible thanks to the public.php/webdav endpoint. --- apps/files/ajax/upload.php | 7 +- apps/files/js/files.js | 2 +- apps/files/templates/list.php | 11 --- apps/files_sharing/ajax/list.php | 96 -------------------- apps/files_sharing/js/public.js | 16 +++- apps/files_sharing/tests/js/publicAppSpec.js | 20 +++- 6 files changed, 35 insertions(+), 117 deletions(-) delete mode 100644 apps/files_sharing/ajax/list.php diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index a784642728f..18e9cfe6117 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -41,7 +41,6 @@ OCP\JSON::setContentTypeHeader('text/plain'); // If not, check the login. // If no token is sent along, rely on login only -$allowedPermissions = \OCP\Constants::PERMISSION_ALL; $errorCode = null; $l = \OC::$server->getL10N('files'); @@ -60,8 +59,6 @@ if (empty($_POST['dirToken'])) { \OC_User::setIncognitoMode(true); - // return only read permissions for public upload - $allowedPermissions = \OCP\Constants::PERMISSION_READ; $publicDirectory = !empty($_POST['subdir']) ? (string)$_POST['subdir'] : '/'; $linkItem = OCP\Share::getShareByToken((string)$_POST['dirToken']); @@ -207,7 +204,7 @@ if (\OC\Files\Filesystem::isValidPath($dir) === true) { $data['originalname'] = $files['name'][$i]; $data['uploadMaxFilesize'] = $maxUploadFileSize; $data['maxHumanFilesize'] = $maxHumanFileSize; - $data['permissions'] = $meta['permissions'] & $allowedPermissions; + $data['permissions'] = $meta['permissions']; $data['directory'] = $returnedDir; $result[] = $data; } @@ -234,7 +231,7 @@ if (\OC\Files\Filesystem::isValidPath($dir) === true) { $data['originalname'] = $files['name'][$i]; $data['uploadMaxFilesize'] = $maxUploadFileSize; $data['maxHumanFilesize'] = $maxHumanFileSize; - $data['permissions'] = $meta['permissions'] & $allowedPermissions; + $data['permissions'] = $meta['permissions']; $data['directory'] = $returnedDir; $result[] = $data; } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 6bdd14ac65d..e33b8354437 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -207,7 +207,7 @@ */ lazyLoadPreview : function(path, mime, ready, width, height, etag) { console.warn('DEPRECATED: please use lazyLoadPreview() from an OCA.Files.FileList instance'); - return OCA.Files.App.fileList.lazyLoadPreview({ + return FileList.lazyLoadPreview({ path: path, mime: mime, callback: ready, diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php index 7ebf80ee8b2..04550f945b6 100644 --- a/apps/files/templates/list.php +++ b/apps/files/templates/list.php @@ -1,16 +1,5 @@